⚡️ Cheaper expWad and lnWad via symmetric rationals - #1546
Open
ddallaire wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Cheaper
expWadandlnWadusing symmetric rational approximations, and a round-to-nearest 2⁹⁶-precision final step forlambertW0Wad.expWad: a diagonal rational approximant of exp satisfies
q(v) = p(-v), so splitting the numerator into even and odd partsp = E(v²) + v·O(v²)makes the denominatorE − v·O, i.e. free. The core drops from 8 muls / 11 constants to 5 / 5 (−16% gas).lnWad:
ln(x) = ln2/2 + 2·atanh(s)withs = (x − √2)/(x + √2). atanh is odd, so the rational only has odd terms, and the √2 centering costs nothing (the tail'sk·ln2just becomes(2k+1)·ln2/2) while shrinking the fit domain enough for a (3,3) rational ins². 12 muls / 14 constants become 7 / 7 (−13% gas). Floor rounding convention unchanged, none of the existing ln test vectors move, andlnWad(1e18)is now exactly 0.lambertW0Wad: the final Iacono–Boyd step inherited
lnWad's last-wei rounding noise, which is what the hand-tuned nudges were calibrated against. It now inlines the ln core at 2⁹⁶ precision and rounds once, puttingWwithin one wei of correctly rounded in that branch (98% exactly rounded, from 46%), and slightly cheaper overall since the cheaper exp/ln inside the iterations pay for it.Measured accuracy is unchanged against a 140-digit reference: exp at the same 9.68e-18 pipeline floor with the same worst cases, ln within 1 wei. Every constant is reproducible from a script, unlike the previous ones (see the note in the test file). Details, derivations, benchmarks, and proofs here.
Also updated the exact test vectors that moved; several known values are now the correctly rounded ones (
exp(-3), the omega constant,W(2**71 - 1),W(2**80 - 1)), and the rest reshuffle by a wei in both directions within the unchanged error envelope, net toward truth (details in the repo above).Checklist
Ensure you completed all of the steps below before submitting your pull request:
forge fmt?forge test?