Reductions, scans and combinations
These operations use scalar kernels; a SIMD engine reports fallback: true. The type contract extends the same fixed algorithms to f64.
Reductions
All reductions return a JavaScript number; there is no vector out. dot(a, b) requires equal lengths and does not broadcast. Read-only inputs may overlap. Resident reductions read backend allocations directly without copying the complete input to JS or allocating a result vector.
Execution follows one left-to-right sequence: no parallel blocks, reordering or FMA. f32 values widen exactly to f64; calculations and return values use f64.
| Operation | Algorithm | Empty input |
|---|---|---|
sum | Neumaier compensated sum starting at +0 | +0 |
product | Sequential f64 multiplication starting at 1 | 1 |
mean | Compensated sum divided by length | NaN |
dot | f64 products accumulated with compensated summation | +0 |
l1Norm | Compensated sum of f64 absolute values | +0 |
squaredNorm | Compensated sum of f64 squares | +0 |
l2Norm | Scaled sum of squares, then scale × sqrt(ssq) | +0 |
variance/stddev | Centered two-pass variance; stddev takes its square root | NaN |
reduceMin/reduceMax | Propagate NaN; prefer -0/+0 respectively | +Infinity/-Infinity |
argMin/argMax | First NaN; otherwise apply zero-sign preference before choosing the first equal extremum | -1 |
Compensation starts with (sum, correction) = (+0, +0). For a finite next = sum + x, add (sum - next) + x or (x - next) + sum to correction, choosing according to the larger absolute operand. Return sum + correction. When next is nonfinite, clear correction to +0 so compensation does not turn finite-plus-infinity into an extra NaN. Existing NaN remains NaN. Products do not short-circuit at zero, infinity or NaN.
l2Norm starts at (scale, ssq) = (0, 1) and skips zeros. If abs(x) > scale, set ssq = 1 + ssq * (scale / abs(x))² and update scale; otherwise add (abs(x) / scale)². Infinity is recorded while continuing to check for NaN. NaN takes precedence over infinity; an all-zero norm is +0.
Variance first computes the compensated mean, then a compensated sum of (x - mean)², divided by n - ddof. ddof defaults to 0 and must be a nonnegative safe integer, otherwise a RangeError is thrown. n <= ddof, NaN or infinite input produces NaN. ddof is not narrowed to f32 or u32.
Numerical reductions propagate NaN. Same-sign infinities retain their sign in sum/mean; opposing infinities give NaN. Dot and product follow IEEE 0 * Infinity. Intermediate underflow or overflow cannot be recovered. sum([-0]) is +0 and product([-0]) is -0. NaN payloads are unspecified.
Scans and combinations
Scans are inclusive prefixes. The first element initializes a nonempty scan directly, so cumsum([-0]) preserves -0. Each later addition or multiplication rounds to f32. cummin/cummax retain NaN and signed-zero rules. Empty scans return empty vectors. Exact in-place output is allowed; partial overlap is rejected before execution.
| Interface | Fixed evaluation order |
|---|---|
scaleAdd(x, scale, bias, options?) | f32(f32(x × f32(scale)) + f32(bias)) |
mulAdd(a, b, c, options?) | f32(f32(a × b) + c) |
lerp(a, b, t, options?) | f32(a + f32(f32(b - a) × t)) |
scaleAdd requires numeric scale and bias. The second and third operands of mulAdd/lerp may independently broadcast, with scalars rounded before use. The first operand is a vector; vector lengths match. Output may exactly alias any input. Validate every operand before writing. Intermediate overflow is possible.
ABI and verification
Reduction status and the f64 result travel separately. N-API returns f64; Wasm returns a status followed by a synchronous read of a result slot. The slot is reset to NaN before each call and must not be read as success after an error. The Wasm module has no imported callbacks, threads or shared memory, so no reentry occurs between these exports. Pointers must identify live matching allocations.
Special values, zero signs, indices, scans and combinations use exact assertions, except NaN payloads. General finite f32 reductions are checked against independent BigInt-expanded and analytic data with |actual - expected| <= max(1e-300, |expected| * 1e-12). Cases include cancellation around 2^100, f64 products, large means with small variance, subnormals and maximum finite f32. This is a dataset acceptance budget, not a universal relative-error guarantee for ill-conditioned inputs. The algorithm is independent of SIMD width; equivalence is claimed only for actually executed targets. See support and compatibility.