Skip to content

Numeric headroom: 64-bit Rational overflows on realistic lab statistics — 128-bit intermediates or a wider representation? #1

Description

@christianparpart

Problem

formula::Rational stores a 64-bit numerator and denominator. Every node computes exactly and reports overflow as an error (never wraps), so nothing returns a wrong number — but realistic lab data can run out of range, turning a valid calculation into an error.

The overflow census (docs/numeric-headroom.md, built with FORMULA_OVERFLOW_CENSUS) measures how many of the 63 value bits real formulas use:

  • Most formulas and all examples keep 5–60 bits of headroom.
  • Dispersion statistics of masses near 40 g (six determinations):
    • sample variance: 11 bits left at 4 dp, 4 at 5 dp, overflows in 423 of 1000 samples at 6 dp;
    • outlier rejection by 7/4 standard deviations: 7 bits at 4 dp, 0 at 5 dp, overflows in 897 of 1000 at 6 dp.
  • Least squares on readings with 3 decimals overflows from 34 points on (57 of 127 sizes between 2 and 128).
  • A cylinder's strength 4F/(πd²) at F = 89.3 kN overflows at 15 of 61 diameters between 100 and 160 mm.

Values are held in coherent SI units. For the variances and strengths, the exact result in SI (kg², Pa) needs 64 bits or more, while the same result in the declared unit (g², MPa) fits in at most 45 bits. The overflow happens in the SI working value, not in the answer the caller receives.

Options

Option A: 128-bit intermediates

Keep Rational at 64 bits; compute each operation (products, cross terms, gcd reduction) in 128-bit integers and reduce before storing.

  • Rescues intermediate overflow (e.g. least squares, some variances).
  • Not enough on its own where the stored SI result itself exceeds 64 bits. It suffices only if, in addition, results are converted to their declared unit inside the wide arithmetic — i.e. nodes stop materialising values in SI — or such statistics are evaluated in a scaled unit.
  • MSVC has no __int128; needs a portable 128-bit type (e.g. _umul128/_udiv128 or a small hand-written type).

Option B: a wider stored representation

Offer a wider Rep (e.g. a fixed-width 128-bit rational) through the existing RepTraits customisation point, selectable per formula or globally.

  • Covers every measured case without changing how values are stored or converted.
  • Larger values in every node and trace step; slower; wider type in the public API.

Decision needed

  1. Option A alone, option A plus declared-unit storage, or option B?
  2. docs/numeric-headroom.md states the rule for acting: any realistic case with fewer than 8 bits of headroom calls for wider arithmetic. The cases above meet it.

The census page is generated and checked in CI, so its figures update automatically when either option lands.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions