Skip to content

Preserve mean accumulator state and recover extreme means and standard deviations - #176

Merged
jmh530 merged 7 commits into
libmir:masterfrom
jmh530:codex/univariate-review
Oct 18, 2026
Merged

jmh530 merged 7 commits into
libmir:masterfrom
jmh530:codex/univariate-review

Conversation

@jmh530

@jmh530 jmh530 commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Means and standard deviations can be representable even when their intermediate sums or variances overflow or underflow. This PR adds recovery for replayable floating-point inputs and preserves saved summation state when merging mean accumulators.

Changes

  • Merge matching mean summators directly when supported, retaining partial sums and compensation that scalar conversion discarded. Centralize this policy in an internal helper with compile-time capability detection and the existing scalar fallback for summators such as decimal.
  • Retry nonfinite means using scaled precise summation. Keep very small observations in a separate unscaled sum so recovery does not erase subnormal remainders during cancellation.
  • Retry nonfinite, negative, zero, or subnormal variances when calculating standard deviation. Use power-of-two scaling and compensated two-pass accumulation, with a fixed reference observation to avoid introducing spread into constant inputs.
  • Preserve existing contracts, nonfinite-input handling, and the zero-centered meaning of assumeZeroMean. Save forward-range traversal state before consuming the input.
  • Document the large-integer conversion limitation and the option of subtracting a known integer offset before calculating variance.

For example, the mean of two maximum finite values now remains finite. Likewise, the sample standard deviations of [-1e200, 0, 1e200] and [-1e-200, 0, 1e-200] can be recovered even though their variances exceed the representable range of double.

Scope and performance

Ordinary finite means and positive normal variances retain their selected algorithms. Single-pass inputs do not receive recovery. This does not generally repair finite cancellation errors, inaccurate positive normal variances, streaming accumulator overflow, or integer differences lost during floating-point conversion.

Paired local benchmarks found no consistent material slowdown for ordinary larger floating-point arrays. Large constant arrays incurred approximately 24–26% overhead in standard deviation because zero variance requires checking whether the observations are genuinely identical.

Validation

  • Full Windows LDC suite: 59 modules passed.
  • Optimized Windows DMD with DIP1000: 12 modules passed.
  • Optimized Linux LDC: 11 modules passed before the final helper extraction.
  • Targeted mean recovery comparisons against exact represented-input references, and 545 standard-deviation fallback cases checked against exact rational variance with a 100-digit square root.
  • Regression coverage includes compensated and precise merges, decimal fallback, source preservation, empty/self merges, extreme magnitudes, subnormal cancellation, sample/population results, strided slices, and shared-cursor forward ranges.

AI-Assisted-By: Codex (GPT-6 Astra Medium)

@jmh530
jmh530 force-pushed the codex/univariate-review branch from d768613 to ca7b216 Compare October 18, 2026 21:33
@codecov

codecov Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Merge matching-element-type summators directly instead of converting
the incoming accumulator to a scalar sum. The conversion discarded
saved corrections and precise overflow information before subsequent
observations could cancel the large terms.

Use the summator's existing merge operation without changing public
fields, scalar insertion, or batch accumulation. Retain the existing
behavior for other element types.

Add regressions for compensated low-order contributions, precise
overflow followed by cancellation, source preservation, and empty
and self merges.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
Retry nonfinite means when the input supports an independent saved
traversal. Finite observations such as two maximum values can have
a representable mean even when their raw sum overflows.

Accumulate large observations with power-of-two scaling and retain
tiny observations in a separate unscaled precise sum. Combine the
subtotals before rounding when the unscaled subtotal is finite,
preserving small remainders from cancellation between the groups.
Otherwise divide before restoring the scale.

Keep the selected summation algorithm for ordinary finite results
and preserve its handling of nonfinite converted observations.
Save forward ranges before consumption and support flattened slice
traversal. Document that single-pass inputs, streaming accumulators,
and finite cancellation errors are outside this recovery path.

Add regressions for extreme finite values, subnormal cancellation,
arrays and strided slices, shared-cursor forward ranges, single-pass
inputs, and nonfinite observations across float, double, and real.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
Computing sqrt(variance) can return zero or infinity even when the
standard deviation is representable. Retry nonfinite, negative, zero,
and subnormal variances for replayable floating-point inputs.

Normalize observations by a power of two and use compensated two-pass
accumulation. Subtract a fixed normalized observation before centering
to avoid introducing spread into identical large values. Preserve the
zero-centered definition of assumeZeroMean and use a cheaper equality
check for zero-variance constant inputs.

Keep the selected algorithm for positive normal variances, preserve
existing contracts and nonfinite-input behavior, and leave single-pass
inputs unchanged. Use direct loops to retain allocation-free operation.
This does not repair inaccurate positive normal variances.

Add regressions for extreme and subnormal magnitudes, sample and
population results, constant inputs, varargs, strided slices, and saved
forward-range cursors. Document recovery behavior and update the naive
algorithm example to account for recoverable cancellation.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
Explain how converting large integer observations to floating-point
accumulators can discard small differences and produce zero variance.
Illustrate the limitation with five consecutive long values near 2^60,
whose sample variance is 2.5.

Describe subtracting a known common offset before conversion as a
workaround, provided the integer subtraction does not overflow.
Clarify that this translation is unsuitable for assumeZeroMean and
that standard deviation's floating-point recovery does not repair
lost integer precision.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
Extract the summator merge policy into an internal mergeSummator helper.
Merge matching element types directly when the operation compiles,
preserving saved partial sums and corrections. Otherwise retain the
existing scalar conversion path and its constraints.

Use the helper in MeanAccumulator to restore compatibility with decimal
summation, whose summator currently lacks a direct merge operation.
Keep capability detection entirely at compile time, with counts and
statistical correction formulas remaining the caller's responsibility.

Document the distinct-source requirement for self merges. Add regressions
for const sources, compensated-state preservation, decimal merging, and
empty and self merges. Register the helper module with Meson.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
Explain how mergeSummator preserves summation state when direct merging
is supported and falls back to scalar conversion otherwise. Clarify
that callers manage observation counts and statistical corrections.

Follow the univariate internal modules' documentation style by stating
the helper's package visibility and linking to the public statistical
functions.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
Exercise the recovery fallbacks through the public assumeZeroMean API,
which has no minimum-count contract. Verify that empty population input
and a zero-valued singleton sample preserve their NaN results rather
than attempting recovery without observations or a nonzero scale.

Also verify that the singleton's population standard deviation is zero.
These regressions cover both previously missed fallback returns without
changing the implementation or input contracts.

AI-Assisted-By: Codex (GPT-6 Astra Medium)
@jmh530
jmh530 force-pushed the codex/univariate-review branch from 00c1955 to a2fed35 Compare October 18, 2026 22:06
@jmh530
jmh530 merged commit 8fadcd8 into libmir:master Oct 18, 2026
26 checks passed
@jmh530
jmh530 deleted the codex/univariate-review branch October 18, 2026 22:19
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.

1 participant