nk 1.0.0
C++ Numerical Computing Runtime
Loading...
Searching...
No Matches
nan_reductions.hpp
1// ops/include/nk/ops/nan_reductions.hpp
2//
3// Internal contract for single-pass NaN-skipping reductions used by
4// nansum / nanmean in stats.cpp. SIMD-dispatched (Highway) when
5// NK_WITH_SIMD=ON, scalar otherwise.
6//
7// Phase P2 of project_perf_optimization_plan.md — replaces the two-pass
8// compactNonNan+sum pattern (one full read for compaction, one for sum)
9// with a single read that masks NaN lanes to zero before accumulation
10// and counts valid lanes in parallel for the mean.
11
12#pragma once
13
14#include <cstddef>
15
16namespace nk::ops {
17
18// Single pass over [p, p+n). NaN positions contribute 0. Returns the
19// sum of the non-NaN values. Empty / all-NaN input returns 0.
20double nanSumScan(const double *p, std::size_t n);
21
23 double sum;
24 std::size_t count;
25};
26
27// Single pass returning both the sum (NaN→0) and the count of non-NaN
28// elements. The caller computes mean = count > 0 ? sum/count : NaN.
29NanSumCount nanSumCountScan(const double *p, std::size_t n);
30
31// Single-pass min / max over [p, p+n) skipping NaN. NaN lanes are
32// masked to the neutral element (+inf for min, -inf for max) before the
33// SIMD reduction. Returns NaN for empty / all-NaN slices (matches
34// MATLAB's nanmin / nanmax convention).
35double nanMaxScan(const double *p, std::size_t n);
36double nanMinScan(const double *p, std::size_t n);
37
38// Two-pass NaN-skipping variance:
39// pass 1: nanSumCountScan -> mean (NaN if count == 0)
40// pass 2: SIMD sum of (x - mean)^2 over non-NaN lanes only
41// Result divided by (count - {0,1}) per the normFlag (matches MATLAB
42// var(x, 0/1) semantics). All-NaN -> NaN; one valid value -> 0 for
43// normFlag==1, NaN for normFlag==0.
44double nanVarianceTwoPass(const double *p, std::size_t n, int normFlag);
45
46} // namespace nk::ops