Phase 1 was bit manipulation. Phase 2 is the actual math — sqrt and cbrt, exp and log and pow, the trig family, the hyperbolic family. Twenty-four base functions, three precision variants each, all of POSIX's transcendental surface that doesn't need a paper-grade approximation library to call "implemented." Both kernels jumped another +5.70 percentage points and now sit at 68% strict POSIX 1003.1-2024.
The algorithms are textbook. The catch is the term count.
First build of Phase 2 came back with eight mathtest failures, all in the same pattern: exp(1.0) ≠ 2.718281828459045 ± 1e-10, atan(1.0) ≠ π/4 ± 1e-9, plus the obvious downstream sin∘asin and tan∘atan identity checks. The functions worked — they just weren't accurate enough. exp's 7-term Taylor series gives ~7e-9 error on the reduced range; my five-coefficient minimax for atan was good for ~12 bits, which is fine for graphics but not for an identity-validating test harness. The fix was unglamorous: extend exp_kernel through 1/12! (13 terms total, error ~8e-15) and replace the atan kernel with Taylor-through-x²¹/21 plus an identity-folding trick that maps |x| in (√2-1, 1] back into the small-x convergence zone via atan(x) = π/4 + atan((x-1)/(x+1)). Rebuild, re-run, all eight failures gone — and the dependent identity checks (pow via exp+log, sin∘asin) all resolved automatically. Lesson: when accuracy needs +6 orders of magnitude and the cost is ten more polynomial terms, just add the terms.
What's actually inside
sqrt is one SSE instruction (sqrtsd / sqrtss) — essentially free. cbrt is six Newton iterations with a bit-trick initial guess. hypot rescales to avoid overflow before squaring. exp range-reduces by ln(2) and runs the 13-term Taylor on the residual, then ldexps back. log normalizes to [√0.5, √2) and runs an atanh-style series on f/(2+f) — the symmetry kills half the rounding error. pow is exp(y·log(x)) with an integer-y fast path and explicit handling for negative bases (only legal at integer y, with parity for the sign). sin/cos fold by 2π and quadrant-select; for arguments past 1e15 the fold degenerates to garbage and the function bails to zero — Cody-Waite multi-precision reduction is a Phase 3 problem. asin/acos go through atan via the standard identities. The hyperbolics are exp-derived with small-|x| Taylor branches to dodge catastrophic cancellation.
The score after one session of math work
| Kernel | Strict yes | Strict % | Session gain |
|---|---|---|---|
| C++ JefeOS | 870 / 1263 | 68.88% | +13.25pp |
| JefeRust | 863 / 1263 | 68.33% | +13.26pp |
That's the combined Phase 1 + Phase 2 movement — 168 cpp entries and 168 rust entries flipped today, going from "no math.h in the tree" to "transcendentals validated end-to-end on a real Hyper-V kernel" in one sitting. The shared-userspace setup means both kernels move in lockstep on libc-only sprints, so the gap between them stayed at 0.55pp.
What's Next
- complex math (
<complex.h>) — 69 mandatory POSIX entries. cabs/carg/conj/cproj plus the cexp/clog/csqrt/csin/etc. families. Most are 1-2 lines on top of the real-valued math we now have. Could push both kernels well past 73% in another single sitting. - fenv (12 entries) — small surface but unlocks proper FE_TONEAREST dispatch in rint/nearbyint and FE_OVERFLOW reporting in scalbn/exp.
- erf/erfc/lgamma/tgamma (12 entries) — the special functions that round out math.h. Need new approximations.
- fma/remainder/remquo/Bessel j0/j1/jn/y0/y1/yn — the long tail of math, +15 entries together.
- Improved trig range reduction at very large |x| via Cody-Waite multi-precision — fixes the bail-out at 1e15.