nx_pow10.nx
buildroot/runtime/nx_pow10.nx
about
nx_pow10.nx -- SHARED NUMERIC rung: base-10 exponential and logarithm in
pure integer arithmetic. Extracted because two unrelated lanes needed the
same primitive -- peptide ionisation fractions (Henderson-Hasselbalch) and
thermal death kinetics (D/z values) are both decade-log physics -- and a
physical primitive with two copies is a drift waiting to happen.
HOW IT WORKS. A 10-entry mantissa table holds 10^0.0 .. 10^0.9 scaled by
1000; any exponent splits into whole decades (repeated x10) plus a
fractional part read from the table. ilog10_milli is the same table run
backwards: normalise into [1, 10), find the bracketing pair, interpolate.
INTERPOLATED, AND THE ERROR IS BOUNDED AND SIGNED. Nearest-entry lookup
alone is 0.1 log units granular = up to 12% error, which is far too coarse
for a food-safety lethality calculation. Linear interpolation between
table entries drops that to <=0.7%. Because 10^x is CONVEX, a chord lies
above the curve, so interpolation always returns a value >= the true one.
That sign is not incidental -- callers computing a lethality with a
NEGATIVE exponent (process cooler than reference) get a slightly
UNDER-stated result, which is the safe direction. A caller relying on a
positive exponent should carry margin; see nx_thermal_process, which does.
⚠THAT BOUND WAS WRONG UNTIL 2026-07-25 AND SAID <=0.3%. This file had no
gate of its own -- it was exercised only through its callers, so nothing
ever checked its self-description. nx_pow10_test now MEASURES the bound
via the functional equation 10^a*10^b = 10^(a+b), scanning the decade for
the worst case: 13 permil on the doubled identity, hence ~6.5 permil on a
single evaluation. That matches the closed form for a chord over a convex
function, (1+r)/2/sqrt(r) - 1 with r = 10^0.1, which is 0.664%. The old
figure understated the error by a factor of two.
The one caller that reasons about this numerically (nx_thermal_process,
botulinum cook adequacy) was re-checked against the corrected figure and
its conclusion is UNCHANGED: 0.7% is still an order of magnitude inside
the ~19% margin the 3.0 min industry F0 target carries over the 2.52 min
12D floor. The claim was wrong; the safety verdict it supported was not.
Units: _q3 = value x 1000, _milli = value x 1000.
Grounding: standard_base10_logarithm_identities (no citation needed beyond
the definition; the gate checks against exact known values).
dependencies 1 imports · 6 importers
imports: nx_syscalls.nx
imported by: nx_labsci_svc.nxnx_peptide.nxnx_shelf_life.nxnx_stability.nxnx_stability_rh.nxnx_thermal_process.nx
structs
| none |
consts
| 45 | const IP10_MAGIC_1259: i64 = 1259 |
| 46 | const IP10_MAGIC_1585: i64 = 1585 |
| 47 | const IP10_MAGIC_1995: i64 = 1995 |
| 48 | const IP10_MAGIC_2512: i64 = 2512 |
| 49 | const IP10_MAGIC_3162: i64 = 3162 |
| 50 | const IP10_MAGIC_3981: i64 = 3981 |
| 51 | const IP10_MAGIC_5012: i64 = 5012 |
| 52 | const IP10_MAGIC_6310: i64 = 6310 |
| 53 | const IP10_MAGIC_7943: i64 = 7943 |
| 54 | const IP10_MAGIC_10000: i64 = 10000 |
| 55 | const IP10_MAGIC_1000000: i64 = 1000000 |
| 57 | const IP10_INVALID: i64 = 0 - 1 |
| 61 | const IP10_CLAMP_MILLI: i64 = 6000 |
functions
| 65 | func ipow10_mantissa_q3(tenth: i64) -> i64 |
| 81 | func ipow10_q3(d_milli: i64) -> i64 |
| 109 | func ilog10_milli(v_q3: i64) -> i64 |