← board

math: the twelve absent names, measured

Swept 2026-08-15, one name per program, pxx against CPython — the successor measurement to [[bug-nilpy-math-surface-remaining-gaps-and-degrees-association]] and [[bug-n-math-trunc-and-log-need-frontend-intercepts]], which closed the names they measured.

39 of 51 agree exactly, including the ones most likely to have drifted: lcm, comb, perm, prod, isclose, modf, fmod, degrees, radians, hypot, copysign, factorial, gcd, trunc, log(x), pow, sqrt, log2, log10, all six trig/hyperbolic pairs that exist, pi, e, tau, inf, nan.

Twelve are absent. Every one fails at COMPILE time as undefined variable, so nothing here is a silent wrong answer:

isqrt(17)      log1p(0)     expm1(0)     atan2(1,1)
asinh(0)       acosh(1)     atanh(0)     isfinite(1.0)
dist([0,0],[3,4])           remainder(7,3)
ldexp(1,3)     frexp(8)

The split that decides how to land them

Four are EXACT — no transcendental, no rounding question, so the standing policy against mapping a 1-ulp-off RTL routine does not apply and they can be written in pylib today:

Eight inherit the ulp policy and must not be mapped to an RTL routine until that routine is correctly rounded — mapping them would trade a loud undefined variable for a silently wrong last digit, which is the trade this project has refused twice already:

Blocked in the real sense on [[bug-b-rtl-math-transcendentals-lose-argument-reduction]] and the correctly-rounded-libm work, not on this table.

Gate

.npy diffed against CPython for whichever names land: the four exact ones with their edge cases (isqrt(0), isqrt of a perfect square, ldexp denormal and overflow, frexp(0), frexp of a negative, isfinite over nan/inf/finite), and a control that the 39 agreeing names still agree.

The table's COMMENT has gone stale, and it gives atan2 the wrong reason

Measured 2026-09-08 (compiler/pascal26 a7b03135f504), reaching this ticket from the lekkerzeilen target, whose hud.py wants math.atan2.

The comment above the math.* mapping table in compiler/pyparser.inc says:

math.log / math.pow / math.atan2 are NOT here — they need a transcendental (Ln, a correctly-rounded pow) and a BUILTIN unit cannot reach one

Two of the three named now work, and so does the function that most directly refutes the stated reason:

pxx CPython
math.log(2.718281828) 0.9999999998311266 identical
math.pow(2.0, 10.0) 1024.0 identical
math.hypot(3.0, 4.0) 5.0 identical

hypot needs Sqrt, so "a builtin unit cannot reach the RTL" is not what keeps atan2 out today — the ULP POLICY above is, and that is a completely different reason with a completely different fix.

This misroutes, and it misrouted this seat. Reading only the comment, the obvious conclusion is that atan2 needs a lowering redesign, and the obvious cheap fix is a table row — lib/rtl/math.pas:63 already declares function ArcTan2(y, x: Double): Double and the rows just below resolve math.asin -> ArcSin by exactly that rename. That fix is the one this project has refused twice, and it would ship a silently wrong last digit in place of a loud undefined variable. The comment should name the ulp policy and point here; it currently names a reachability wall that three working functions disprove.

A note for a caller that does not need the last digit: the refusal is a GLOBAL policy about what math.atan2 may silently mean, not a claim that no program may use ArcTan2. A target permitted to change its own source (see [[umbrella-lekkerzeilen-compiles-and-runs-under-nilpy]], where the owner has licensed exactly that) can call an explicit helper and carry the 1 ulp knowingly — a HUD heading does not care. Do not read this as licence to map the name.


atan2 alone is the largest single blocker on the lekkerzeilen umbrella (2026-09-09)

Measured over lekkerzeilen/*.py, first error only: math.atan2 is the first failure in five of the twenty-three modules — hud, rig, sim, traffic, vessel — which is more than any other cause, ahead of the closed-world dispatch fork (4) and import array (3). The umbrella is owner-directed at prio 75, so this ticket's effective prio already inherits that; what the body did not say is that ONE of the twelve names carries almost all of it.

That does not by itself overturn the split above — atan2 is in the eight that inherit the do-not-map-a-1-ulp-off-routine policy, and this is a ranking fact, not an accuracy argument. It is recorded because whoever picks this up should know that landing atan2 and nothing else is worth five modules, and that the question to settle first is the policy one, not the implementation.

Beside it, for whoever sweeps this again: math here resolves far enough to report no member atan2 came of the qualifier math, i.e. the import bound something. That is the loud-at-compile behaviour the sweep claimed, re-observed 25 days later on real source.

The residual has no application demand — measured 2026-09-20 (frankH)

Population: every math.<name> occurrence in the two target applications, /home/neo/lekkerzeilen and /home/neo/tuxspaceprogram, *.py at their working trees today. Oracle for the value rows: CPython 3.14.4. Compiler at 47841c55b.

29 distinct names are used, 1129 occurrences. NONE of the fifteen absent names (acosh asinh atanh cbrt erf erfc exp2 gamma lgamma log1p nextafter remainder sumprod ulp) appears in either tree. The sixteenth, dist, is used 23 times and landed on 2026-09-19.

And the surface they DO use is already correct: all 27 comparable rows agree with CPython exactly -- sin cos radians sqrt pi hypot degrees atan2 floor dist ceil asin tan acos exp log inf log10 copysign pow isfinite isnan isinf fmod atan sinh nan log2 cosh, printed at %.12g and diffed whole.

So this ticket's remainder is real and has zero measured demand from the programs we are trying to compile. Anyone ranking it should rank it on something other than application need, and the F-lane rule applies to what is left: a missing function a working program CALLS is a bug, and none of these is called.

What would retire this row: a target application importing one of the fifteen. Re-run the census (grep -rhoE '\bmath\.[a-z_0-9]+' over both trees) rather than trusting this count -- it is a snapshot of two working trees on one day, and the trees move.