Skip to content

Commit 2bf443a

Browse files
committed
DEBUG: add branch-localization + SIMD-disabled pinning probes to ft_repro
1 parent 8828ddc commit 2bf443a

1 file changed

Lines changed: 60 additions & 0 deletions

File tree

ci_debug/ft_repro.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@
88
This is a diagnostic, not a gate: it never raises to the shell (always exits 0),
99
so both wheels' output is captured in the CI log.
1010
"""
11+
import os
12+
import subprocess
1113
import sys
1214

15+
try:
16+
sys.stdout.reconfigure(line_buffering=True) # keep subprocess output in order
17+
except Exception: # noqa: BLE001
18+
pass
19+
1320
import numpy as np
1421
import numpy_quaddtype as nq
1522
from numpy_quaddtype import QuadPrecision as Q
@@ -60,6 +67,30 @@ def run(label, fn):
6067
run("float(Q('inf'))==float('inf')", lambda: float(Q("inf")) == float("inf"))
6168
run("type(float(Q('inf')))", lambda: type(float(Q("inf"))).__name__)
6269

70+
# ---- BRANCH LOCALIZATION: same np.isinf, different input stride/shape ---------
71+
# The CPU-dispatched DOUBLE_isinf loop branches on the INPUT stride:
72+
# 0-D scalar -> input stride 0 -> NCONTIG branch
73+
# 1-D contig -> stride == itemsize -> CONTIG branch (this one works on FT-win)
74+
# 1-D non-cont -> stride != itemsize, !0 -> NCONTIG branch (stride != 0)
75+
# Comparing these tells us whether the fault is stride==0 only, any NCONTIG, or the
76+
# small-count scalar tail in general.
77+
print("[%s] BRANCH LOCALIZATION (isinf, varying input stride/shape):" % TAG)
78+
run("0-D isinf(np.array(np.inf))", lambda: bool(np.isinf(np.array(np.inf))))
79+
run("1-Dx1 isinf([inf])[0]", lambda: bool(np.isinf(np.array([np.inf]))[0]))
80+
run("1-Dx2 isinf([inf,inf])[0]", lambda: bool(np.isinf(np.array([np.inf, np.inf]))[0]))
81+
run("1-Dx9 isinf([inf]*9).all()", lambda: bool(np.isinf(np.array([np.inf] * 9)).all()))
82+
run("1-Dnc isinf([inf,1][::2])[0]", lambda: bool(np.isinf(np.array([np.inf, 1.0])[::2])[0]))
83+
84+
# Same-dtype unary ufuncs go through the SCALAR FAST PATH (try_trivial_scalar_call),
85+
# unlike isinf/isnan (bool output) which bail out of it. If these are ALSO wrong,
86+
# the fast path is implicated; if they are fine, the fault is the normal 0-D path.
87+
print("[%s] SAME-DTYPE fast-path scalar ufuncs (should be unaffected if 0-D path):" % TAG)
88+
run("negative(np.inf)", lambda: float(np.negative(np.inf)))
89+
run("negative(np.float64 inf)", lambda: float(np.negative(np.float64("inf"))))
90+
run("absolute(np.float64 -inf)", lambda: float(np.absolute(np.float64("-inf"))))
91+
run("sqrt(np.float64 inf)", lambda: float(np.sqrt(np.float64("inf"))))
92+
run("signbit(np.float64 -inf)", lambda: bool(np.signbit(np.float64("-inf"))))
93+
6394
print("[%s] string -> quad (special values + a couple normals):" % TAG)
6495
for s in ["inf", "-inf", "nan", "-nan", "Infinity", "1.5", "0.1"]:
6596
run("Q(%r)" % s, lambda s=s: "float=%s bits=%s" % (fval(Q(s)), bits(Q(s))))
@@ -94,4 +125,33 @@ def _mm():
94125
return fval(np.matmul(A, Im)[0, 0])
95126
run("matmul(inf-matrix, I)[0,0]", _mm)
96127

128+
# ---- SIMD-DISABLED re-check: force the baseline (non-dispatched) loop -----------
129+
# NPY_DISABLE_CPU_FEATURES is read at import, so re-run the key scalars in a fresh
130+
# subprocess with every dispatched CPU feature disabled. If scalar isinf/isnan then
131+
# become correct on FT-Windows, the fault is the CPU-dispatched SIMD DOUBLE_isinf
132+
# codegen; if still wrong, it is the baseline/generic path.
133+
print("[%s] SIMD-DISABLED re-check (baseline loop via NPY_DISABLE_CPU_FEATURES):" % TAG)
134+
try:
135+
import numpy._core._multiarray_umath as _mu
136+
_feats = " ".join(getattr(_mu, "__cpu_dispatch__", []) or [])
137+
except Exception as e: # noqa: BLE001
138+
_feats = ""
139+
print(" could not read __cpu_dispatch__: %s" % e)
140+
print(" dispatched features being disabled: %s" % (_feats or "(none)"))
141+
_mini = (
142+
"import numpy as np;"
143+
"print(' [nosimd] numpy', np.__version__);"
144+
"print(' [nosimd] isinf(np.inf) =', np.isinf(np.inf));"
145+
"print(' [nosimd] isnan(np.float64 nan) =', np.isnan(np.float64('nan')));"
146+
"print(' [nosimd] isinf([inf])[0] =', np.isinf(np.array([np.inf]))[0])"
147+
)
148+
_env = dict(os.environ)
149+
if _feats:
150+
_env["NPY_DISABLE_CPU_FEATURES"] = _feats
151+
sys.stdout.flush()
152+
try:
153+
subprocess.run([sys.executable, "-c", _mini], env=_env, check=False)
154+
except Exception as e: # noqa: BLE001
155+
print(" subprocess failed: %s" % e)
156+
97157
print("########## end probe [%s] ##########\n" % TAG)

0 commit comments

Comments
 (0)