You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
Fixed
Core AD (all modes: Dual, DualVec, Reverse, BReverse, bytecode tape)
Max/Min NaN handling: BReverse::max/min and bytecode eval_forward/reverse_partials now return the non-NaN argument when one input is NaN, matching Float::max/Float::min semantics and the behavior of Dual/Reverse modes.
atan2(0,0) derivative: returns zero gradient (matching JAX/PyTorch convention) instead of NaN from division by zero in x²+y².
powf(x, 0) derivative: correctly returns d/db = ln(x) for x > 0 instead of silently dropping the exponent derivative. d/da = 0 was already correct.
powf(x, y) at x=0: Reverse and bytecode modes now use the y * x^(y-1) form (matching Dual) instead of y * val / x which produces 0/0 = NaN.
powi_exp_decode: deleted broken generic float round-trip decoder (failed for f32 negative exponents); replaced with powi_exp_decode_raw at both call sites.
Taylor / Laurent series
Taylor abs(0): Taylor::abs and TaylorDyn::abs now use the first nonzero coefficient's sign instead of signum(+0.0) = 0, preventing the entire jet from being annihilated.
taylor_cbrt at zero: returns [0, Inf, ...] (signaling the vertical tangent) instead of NaN from ln(0).
taylor_sqrt at zero: runtime guard returns [0, Inf, ...] instead of silent Inf/NaN from division by 2*sqrt(0).
Laurent Add/Sub truncation: promoted from debug_assert to assert! — silent coefficient loss when pole-order gap exceeds K-1 is now caught at runtime.
Bytecode tape
Checkpoint thinning: online checkpoint thinning now maintains uniform spacing after doubling (skip(1).step_by(2) instead of step_by(2)), fixing O(N) recomputation degradation for small checkpoint budgets.
Abs sparse Hessian: reclassified from UnaryNonlinear to ZeroDerivative — d²|x|/dx² = 0 a.e., reducing spurious Hessian sparsity pattern entries.
Added debug_assert for tape variable count overflow (u32::MAX) and contiguous input opcodes.
GPU Taylor kernels (CUDA + wgpu, codegen)
POWI negative bases: GPU Taylor mode now handles negative bases via sign(a)^n * exp(n * ln(|a|)) instead of exp(n * ln(a)) which produced NaN for ln(negative).
POWF at a≤0: added first-order chain-rule fallback when a ≤ 0 (where ln(a) is undefined).
REM Taylor coefficients: c1/c2 now pass through a's jet (d(a%b)/da = 1 a.e.) instead of being zeroed.
_sign in taylor_eval.cu: now matches tape_eval.cu — returns 1 for +0.0 and NaN for NaN (Rust signum semantics).
ATAN2 at b=0: uses direct derivative formula instead of jet_div(a, b) which divided by zero.
CBRT at a=0: returns [0, Inf, ...] instead of NaN from ln(0).
wgpu expm1/ln1p: polynomial approximation for |x| < 1e-4 to avoid catastrophic cancellation.
echidna-optim
Trust-region min radius: added min_radius field to TrustRegionConfig (default F::epsilon()), preventing silent stall from geometric radius collapse.
boundary_tau zero direction: guards ||d||² < epsilon to prevent NaN from degenerate CG directions.
LU singularity threshold: changed from hardcoded 1e-12 to F::epsilon().sqrt(), fixing false negatives for f32 near-singular matrices.
Piggyback adjoint: extra reverse pass with converged lambda_new eliminates O(tol × ||G_x||) error in parameter gradients.
Weighted STDE: estimate_weighted skips zero-weight samples to prevent division by zero in West's algorithm.
Welford accumulator: debug_assert!(sample.is_finite()) catches NaN/Inf inputs in debug builds.
Changed
GPU STDE test parity: refactored tests/gpu_stde.rs to use a generic opcode_tests_for_backend! macro, running all per-opcode Taylor tests on both wgpu and CUDA backends instead of wgpu-only.
TrustRegionConfig: added min_radius: F field (breaking change for direct struct construction; Default impls updated).