Your free trial has ended.
Try the live demo or log in .
By: ValentinHirschi <valentin.hirschi@gmail.com>
Evaluate the divided difference's dilogarithms once in the interpreter NinjaRS's end-to-end Float pentagon (700 and 1000 bits) became 1.4 to 1.9 times slower at 3cbe08d. It evaluates oneloopmaster's exact expressions with Symbolica's interpreter, where the interpreted D0 and C0 of the pentagon's calls went from 8.2e8 and 2.3e8 retired instructions per call at 700 bits before 3cbe08d to 1.8e9 and 5.3e8 (native code was unaffected). 3cbe08d's divided difference tests whether the direct difference cancels, |upper - lower|² 256 < |upper|², before choosing near_difference. Symbolica caches common subexpressions while linearizing, but returns before caching a call of a non-inlined registered function, so every occurrence of such a call is evaluated again: the test made the interpreter evaluate each dilogarithm two or three times per divided difference (the instruction listing of the divided difference called the sheet dilogarithm five times for its two arguments). The native emitter shares the calls, which is why only the interpreter slowed down. The test and the choice now live in a registered selection (sheet_exact::select_body) that takes the two dilogarithms and the gap as arguments, evaluated once; the complements' difference of 3023fa6 shares it. At 700 bits the interpreted D0 and C0 now take 7.9e8 and 2.2e8 instructions per call (4% below the commit before 3cbe08d; at 1000 bits 6% and 7% below). Building the interpreted D0 with its first call still costs 1.8 times what it did before 3cbe08d (0.6 s at 700 bits, once per precision), from the larger contour-box and collinear expressions since. Binary64 and 256-bit results are bitwise unchanged on every route (native, generated, interpreted, SymJIT) over 1,145 collinear and near-threshold rows. tests/expression_construction.rs checks that no interpreted D0 or C0 body (nested bodies included) calls a dilogarithm, or a divided difference of them, twice with the same arguments where the first call dominates (it fails on the previous form). Tests: full suite with generated evaluators passes (231 passed, 7 ignored). Native code regenerated (C0 and D0), C0 and D0 SymJIT assets rebuilt. Oracle sweeps (D0, four seeds; C0, two seeds; native, generated and expression routes, against 149ddff): no row fixed or regressed. Retired instructions per binary64 call on the recorded NinjaRS streams against 149ddff: D0 unchanged, C0 -0.09% (geomean; at most -0.65%). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>