v2.3.1 — Correctness patch
Correctness patch — no API change; upgrading from v2.3.0 is a drop-in swap. Eight issues closed (#102, #105, #106, #112, #115, #116, #117, #118) across five PRs (#120–#124), each with fail-first regression gates. Correctness suite grows 53 → 58.
Fixed
- SIMD:
vector_log_{sse2,avx,avx2,avx512}gained the missing unordered-compare NaN blend — a NaN lane previously exited as 710.188, so LogNormal batchcdf(NaN)returned 1 andpdf(NaN)returned 0 through the public API (#105). - Batch NaN propagation: 16 of 19 distributions returned finite, plausible values for NaN batch inputs (uniform batch
pdf(NaN)gave the full in-support density; Discrete batchcdf(NaN)gave −214748364.7). NaN is now classified ahead of every range check and propagates, mirroring each scalar contract; all 19 distributions are gated (#102). - Von Mises: the κ > 1000 wrapped-normal CDF fallback wrapped x alone instead of x − μ, returning F = 0 where the truth is 1 for every x on the far side of the ±π seam; new κ = 2000/10000 accuracy-gate buckets (#106).
- NegativeBinomial/Geometric:
getQuantile's search bound was cast tointunguarded; past INT_MAX the search collapsed and every quantile returned 0 (Geometric(1e-9).getQuantile(0.5)= 0, truth ≈ 6.93e8). Bound clamped to 2⁵³ before narrowing toint64; the search evaluates the incomplete beta directly (#116). - Stream I/O:
operator>>round-trip was broken for Discrete, Uniform and Beta (whitespace tokenisation vs their own comma-space output); rewritten on Gaussian's getline pattern, output formats unchanged (#115). - CPUID gates: the AVX-512 tier is now gated on AVX-512DQ (the kernels use five DQ intrinsics — F alone is an illegal-instruction fault on redistributed binaries) and on XCR0[7:5] opmask/ZMM state; the AVX2 tier is gated on FMA; the MSVC configure probe executes a DQ instruction;
SIMDPolicyuses the same gates so the two reporting ladders agree (#117). ParallelUtils::parallelForsilently discarded exceptions thrown inside chunks, returning partial output as success. It now waits for all chunks, then rethrows the first exception (#118).WorkStealingPool::parallelForstill swallows by design; the asymmetry is documented.
Changed
- Batch span overloads: the no-aliasing contract (input and output spans must not overlap) is documented at every surface and enforced by a debug-mode assert at the central dispatch point (#112). Zero cost in Release.
tools/accuracy_sweep.cppemits NaN/±inf special rows for the discrete family too; grid grows 5928 → 6063 rows. The regenerated AVX-512 characterization block shows 0 batch-NaN violations and 63 total (all remaining rows belong to the v2.3.2 ±inf-contract and large-parameter classes).libstats.pcis relocatable (prefixderives from${pcfiledir}).
Validation
58/58 correctness native on Zen 4 AVX-512 (MSVC Release, 2026-08-25); CI green on all merges. Kaby Lake (AVX2+FMA) and M1 (NEON) native validation runs are pending and tracked for the v2.3.1 matrix. Full details in CHANGELOG.md and docs/ACCURACY_CHARACTERIZATION.md.
🤖 Generated with Claude Code