Skip to content

Native bit-faithful NNS.reg hot path (gravity, NNS.part, NNS.dep, NNS.copula, single nns_reg_mv entrypoint) - #37

Merged
OVVO-Financial merged 5 commits into
mainfrom
claude/serene-clarke-batq0o
Jun 15, 2026
Merged

Native bit-faithful NNS.reg hot path (gravity, NNS.part, NNS.dep, NNS.copula, single nns_reg_mv entrypoint)#37
OVVO-Financial merged 5 commits into
mainfrom
claude/serene-clarke-batq0o

Conversation

@OVVO-Financial

@OVVO-Financial OVVO-Financial commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Summary

Follow-up to the ARMA forecast-loop optimization (#33, merged). This PR pushes the entire NNS.reg multivariate hot path into the C++ binding layer, each piece a bit-faithful port of the R-faithful pure-Python implementation, wired through the existing _native graceful-fallback pattern. Numeric behavior is unchanged; this is purely an acceleration via the optional native backend, with the Python fallback intact for every uncovered regime.

The existing vendored nns::gravity/partition could not be reused — they derive from a different revision and diverge from the Python the parity suite enforces (e.g. nns::gravity was off by up to ~0.3) — so these are fresh, verified ports.

Changes (5 commits)

  1. gravity_exact — faithful port of nns.dependence._gravity (quartile/binning central tendency), used pervasively for partition centers, regression points, and consolidation.
  2. nns_part_off — faithful port of the noise_reduction="off" path of nns.part.nns_part, the recursive partitioner at the heart of NNS.reg.
  3. nns_dep_pair — faithful port of nns.dependence.nns_dep (xonly partition, directional/global copulas, signed and degree-0 copulas, n-d partial moments, discrete-case gravity combination). Co-moments reuse the verified nns:: kernels. Also adds numpy-exact pairwise summation so all means/sums used as comparison thresholds are bit-identical to numpy — a ~1e-11 difference in a gravity center was enough to flip a discrete partition split, so gravity_exact uses it too.
  4. copula_nd — faithful port of nns.copula._copula (general-d n-dimensional partial moments + discrete/continuous blend), reusing the verified nns::pm_matrix kernel.
  5. nns_reg_mv — single native entrypoint that folds the remaining orchestration (XONLY partition, initial regression points, central point, endpoint values, consolidation/clamping) into one native call. Wired at the multivariate_call branch of _nns_reg_univariate_core for the common regime (noise=off, non-class, non-smooth, standard XONLY branch); other regimes fall through to pure Python.

Because every NNS.reg multivariate caller routes through that branch, the acceleration carries across nns_m_reg and therefore NNS.stack and NNS.boost, not just nns_arma.

Verification

  • Bit-exact (0 ULP) vs the pure-Python implementations over large randomized batteries (continuous, discrete, ARMA-like, dependent, nonlinear): gravity_exact 200k cases; nns_part 8k; nns_dep 16k; copula_nd 40k; nns_reg_mv 6k.
  • Full test suite: 2200 passed, 13 skipped (env-only skips); ruff + mypy clean.
  • End-to-end outputs bit-for-bit identical with the native path on vs off.

Performance (native on vs off, identical output)

Workload Speedup max diff
nns_arma nonlin forecast ~14× 0.0
nns_m_reg ~11× 0.0
NNS.stack ~7.8× 0.0
NNS.boost ~9.4× 0.0

https://claude.ai/code/session_01AN7vrBnRhxGd4eZv6A34VX


Generated by Claude Code

claude added 5 commits June 15, 2026 16:27
The NNS gravity central tendency (nns.dependence._gravity) is called
heavily inside the NNS.reg partition/regression path that nns_arma drives
per-lag, per-step in its nonlin/both recursion. It was pure Python.

This ports _gravity (and its quartile/binning helpers) faithfully to the
C++ binding layer as a new gravity_exact symbol, and routes _gravity
through it via the existing _native fallback. It is intentionally separate
from the vendored nns::gravity, which derives from a different revision and
diverges from the R-faithful Python by up to ~0.3; gravity_exact matches
the Python to floating-point summation order (max relative diff ~9e-12 over
200k randomized cases, exact for normal-scale and discrete inputs).

Full test suite remains green and the nonlin ARMA forecast is bit-for-bit
identical with native on vs off, ~1.6x faster on a representative series.
nns_part is the recursive partitioner at the heart of NNS.reg, which
nns_arma drives per-lag, per-step in its nonlin/both recursion. It was
pure Python with per-depth numpy unique/char operations on small arrays.

This ports the noise_reduction="off" path (the only mode the numeric
NNS.reg / nns_arma hot path uses) faithfully to the C++ binding layer as
nns_part_off, aggregating centers and regression points with the
previously added gravity_exact. The Python wrapper routes through it via
the _native fallback and keeps the pure-Python implementation for the
mean/median/mode paths.

Verified bit-exact against the pure-Python nns_part over 8000 randomized
cases (quadrant labels, prior labels, order, and regression-point values
all identical; worst value diff 0.0). Full suite stays green; the nonlin
ARMA forecast is bit-for-bit identical with native on vs off and the
cumulative native path (gravity + partition) is ~1.9x faster on a
representative series.
Profiling the nonlin nns_arma forecast showed _copula_signed (via
nns_dep -> _dep_pair -> _directional_dep) dominating ~70% of runtime:
nns_dep is called per-lag, per-step through _regression_dependence.

This ports nns_dep faithfully to the C++ binding layer as nns_dep_pair,
covering the xonly partition, directional/global copulas, the signed and
degree-0 copulas, n-d partial moments, and the discrete-case gravity
combination. Co-moments reuse the verified nns:: kernels.

To keep comparison thresholds bit-identical to numpy, it implements
numpy's exact pairwise summation (np_pairwise_sum) for all means/sums,
and gravity_exact now uses it too: a ~1e-11 difference in a gravity
center was enough to flip a discrete partition split and diverge the
dependence result. gravity and nns_dep are now bit-exact (0 ULP) vs the
pure-Python implementations over >200k and >16k randomized cases
respectively (continuous, discrete, ARMA-like, dependent).

Full suite stays green; the nonlin ARMA forecast is bit-for-bit identical
with native on vs off, and the cumulative native path
(gravity + partition + dependence) is ~6.5x faster on a representative
series.
…path

After the native nns_dep landed, profiling showed the multivariate
_copula term in _regression_dependence (pm_matrix + n-d partial moments
over the 3-column scaled matrix) as the dominant remaining cost (~42%)
of the nonlin nns_arma forecast.

This ports nns.copula._copula faithfully to the C++ binding layer as
copula_nd: general-d n-dimensional partial moments (clpm/cupm/dpm)
mirroring the pure-Python formulas with numpy-faithful pairwise means,
and the discrete/continuous copula blend. The partial-moment covariance
matrices reuse the verified nns::pm_matrix kernel; per-column targets are
supplied by the caller (np.mean) so they are already bit-identical.

Verified bit-exact (0 ULP) vs pure-Python _copula over 40k randomized
cases (d=2..4, continuous, discrete, dependent, and the regression-style
duplicated-column 3-col input). Full suite stays green; the nonlin ARMA
forecast is bit-for-bit identical with native on vs off, and the
cumulative native path (gravity + partition + dependence + copula) is
~7.9x faster on a representative series.
Folds the remaining Python orchestration of the NNS.reg multivariate-call
regression-points path into one native call: the XONLY off-noise
partition, initial regression points, central point, endpoint values, and
the consolidation/clamping. Refactors the partition loop into shared
partition_labels / regression_points_from_prior helpers reused by
nns_part_off, and reuses gravity_exact, np_pairwise_sum, and the verified
nns::fast_lm kernel.

It is wired at the multivariate_call branch of _nns_reg_univariate_core
for the common regime (noise=off, non-class, non-smooth, standard XONLY
partition with dependence != 1 and integer dep_order); other regimes fall
through to pure Python. Because every NNS.reg multivariate caller routes
through this branch, the acceleration now carries across nns_m_reg and
thus NNS.stack / NNS.boost, not just nns_arma.

Verified bit-exact (0 ULP) vs the pure-Python multivariate path over 6k
randomized cases (ARMA-like, dependent, independent, nonlinear; varied
orders); the nns_part_off refactor remains bit-exact. Full suite green.
The nonlin ARMA forecast and nns_m_reg Point.est are bit-for-bit
identical with native on vs off, ~14x and ~11x faster respectively on
representative inputs.
@OVVO-Financial OVVO-Financial changed the title Native bit-faithful gravity, NNS.part, and NNS.dep for the NNS.reg/ARMA hot path Native bit-faithful NNS.reg hot path (gravity, NNS.part, NNS.dep, NNS.copula, single nns_reg_mv entrypoint) Jun 15, 2026
@OVVO-Financial
OVVO-Financial merged commit 24dfcb8 into main Jun 15, 2026
4 checks passed
OVVO-Financial pushed a commit that referenced this pull request Jun 15, 2026
Ships the native bit-faithful NNS.reg hot path (gravity, NNS.part,
NNS.dep, NNS.copula, and the single nns_reg_mv multivariate-call
entrypoint) merged in #37, accelerating nns_arma, nns_m_reg, NNS.stack,
and NNS.boost while preserving R-faithful numeric behavior (native path
is optional with a pure-Python fallback).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants