Skip to content

Commit fbd8fae

Browse files
committed
fix(ci): macOS arm64 — gate complex square's x86-FMA residual + the complex NaN-sign contract; refresh benchmark coverage
Follow-up to 8e1f3cd. On the previous run Windows+Ubuntu went green and only test(macos-latest) failed — my Half fix let the suite run past HalfArithKernelTests and unmasked one more arm64 divergence; the docs job advanced past the (now-fixed) inventory diffs to a later stale-artifact step. Both closed here, verified in a clean worktree off origin/journey3 (both test projects build net8+net10; FuzzMatrix 0 fail). 1. NumSharp.Tests(macOS) — NewDtypesUnaryTests.Complex_Square_FmaContraction NDComplexMath.Square dispatches on System.Runtime.Intrinsics.X86.Fma.IsSupported: with x86 FMA it issues vfmaddsub so fma(re,re,-(im*im)) exposes im*im's rounding and square(1e-10+1e-10j).Real == -2.275e-37; WITHOUT x86 FMA (AArch64) it takes the non-fused fallback where re*re and im*im each round to the same 1e-20 and cancel exactly to 0. The test asserted the FMA residual unconditionally, so it failed on the Apple-silicon runner. Gate the residual assertion to Fma.IsSupported (mirroring the kernel's own dispatch, the numpy 2.4.2 win-amd64 reference), assert 0.0 on the fallback, and keep the imaginary/interior/overflow checks on every host. 2. Oracle(macOS) — the complex NaN-SIGN contract, gated to the x86 reference The unpushed complex-NaN commits (760bb5b/298e7c60) made CompareArray compare the complex-unary NaN SIGN by raw bytes (ComplexNanContractOps + DiffHasSignFlip) for EVERY tier, not just the new nan tier — specials(569)/unary_extra(494)/tail(54) all carry complex128 cases. That sign is authored against win-amd64/MSVC-UCRT and holds on the whole x86 family (Windows AND Linux, shared SSE) but NOT on AArch64, where a fresh NaN from a genuine 0/0.inf-inf inside the complex arithmetic carries the CPU's POSITIVE default sign (x86 emits NEGATIVE) — a DiffHasSignFlip hard-fail on a platform artifact. Those tiers' finite complex VALUES are proven cross-platform (macOS-green at 02e6929, before this comparison existed), so the ONLY new arm64 risk is the sign compare itself. Gate nanExact to the x86 family (NanSignIsX86Reference); NaN tokenizes on arm64 exactly as it did when the tiers were last macOS-green. Same host-pin RULE as the RunHostLibmCorpus tiers, applied per-op. Windows/Linux stay the strict gate. 3. docs job — benchmark/coverage/generated was stale audit_coverage.py --check failed (it was hidden behind the coverage/inventory diffs fixed in 8e1f3cd). Its coverage derives from coverage/generated/coverage.json (the file refreshed in 8e1f3cd) plus the committed benchmark *.cs, so it was stale for the same reason. Regenerated; --check now current. LF output, sorted, .as_posix() — the same deterministic generator family proven byte-identical across Windows/ubuntu.
1 parent 8e1f3cd commit fbd8fae

5 files changed

Lines changed: 194 additions & 16 deletions

File tree

benchmark/coverage/generated/coverage.csv

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmark/coverage/generated/coverage.json

Lines changed: 138 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmark/coverage/generated/summary.md

Lines changed: 13 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/NumSharp.Tests.Oracle/Fuzz/FuzzCorpusTests.Kinds.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ public partial class FuzzCorpusTests
3939
"sign", "abs", "absolute"
4040
};
4141

42+
/// <summary>
43+
/// The complex NaN-SIGN contract above is authored against numpy 2.4.2 win-amd64 (MSVC UCRT),
44+
/// and NumSharp reproduces it in managed code + x64 SSE — so it holds bit-for-bit on the whole
45+
/// x86 family (Windows AND Linux, shared deterministic SSE), but NOT on AArch64: a fresh NaN
46+
/// from a genuine 0/0·inf-inf inside the complex arithmetic carries the CPU's default-NaN
47+
/// sign, which is POSITIVE on ARM where x86 emits NEGATIVE. Off the x86 reference the raw-byte
48+
/// NaN-sign compare would hard-fail via <see cref="BitDiff.DiffHasSignFlip"/> on a platform
49+
/// artifact, so the sign contract is gated to x86 and NaN tokenizes elsewhere (the finite
50+
/// complex VALUES in these tiers are proven cross-platform — they were macOS-green before this
51+
/// comparison existed). Same host-pin RULE as the RunHostLibmCorpus tiers, applied per-op.
52+
/// </summary>
53+
private static readonly bool NanSignIsX86Reference =
54+
System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture
55+
is System.Runtime.InteropServices.Architecture.X86
56+
or System.Runtime.InteropServices.Architecture.X64;
57+
4258
// ---- new tiers ---------------------------------------------------------------------
4359

4460
/// <summary>
@@ -171,7 +187,8 @@ private static void CompareArray(
171187
// result dtype, so `abs`/`absolute` (complex128 -> float64) is gated too. Everywhere else NaN
172188
// stays tokenized (a differing payload/sign is non-contractual — order/algorithm-dependent).
173189
bool nanExact = ComplexNanContractOps.Contains(c.Op)
174-
&& (tc == NPTypeCode.Complex || c.Operands.Any(o => o.Dtype == "complex128"));
190+
&& (tc == NPTypeCode.Complex || c.Operands.Any(o => o.Dtype == "complex128"))
191+
&& NanSignIsX86Reference; // win-amd64 NaN-sign contract; tokenize off x86 (arm64)
175192

176193
// Bit-exact to NumPy ("precise") passes HERE, before truth is ever read — matching
177194
// NumPy's bytes is the contract, and truth can never turn a precise result red.

0 commit comments

Comments
 (0)