Repository navigation
Compiled combinatorial functions at whole arguments are exact - #2218
Merged
Merged
Conversation
The compiled binomial took a whole lower argument as a product of ratios in doubles, (n - i)/(i + 1), each rounded, so binomial(54, 45) came out 5317936259.999995 where evaluation gives 5317936260. Of the 2485 binomials with 0 <= k <= n < 70, 1173 were not the integer. The factorial powers and the double factorial, products of whole factors, rounded at each step once a partial product passed 2^53, and so were off in the last places from there. At whole arguments each is now computed exactly and rounded once: - the binomial by binomial(m, i + 1) = binomial(m, i) (m - i)/(i + 1), whose division leaves no remainder, over the shorter of k and m - k, and for a negative n by (-1)^k binomial(k - n - 1, k); - the products in doubles while each partial product is below 2^53, where every step is exact, and past it in EInteger, rounded by EFloat or, for a negative order's reciprocal, by ERational. The Catalan numbers were computed exactly, in #2216, and rounded by (double)BigInteger, which truncates: 246 of the first 1000 were a unit low in the last place, C_32 = 55534064877048200 coming out 55534064877048190. They are rounded by EFloat now. Nothing else in the library rounds a BigInteger to a double for a result. A factor of 0 is checked for before the product, so a partial product past the doubles' range is known to stay past it, and the loop stops there. Checked against evaluation exactly, as doubles, in both compilers: every two-argument function on a grid of 90 whole first arguments, up to 10^12, and 58 whole second arguments from -12 to 45; the binomial past 2^53 and past the doubles, among others at (60, 30), (1100, 550), (3000, 1500) and (-1, 4001); the double factorial from -301 to 320; and the Catalan numbers from 0 to 1000. The expected value is the exact rational rounded once by ERational, since ToNumerics goes through a decimal whose exponent has a floor, and reads 1/299!! as 0. On master 9 of these tests fail. Part of #2195. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2218 +/- ##
=======================================
Coverage 86.64% 86.65%
=======================================
Files 306 306
Lines 67494 67536 +42
Branches 19566 19587 +21
=======================================
+ Hits 58482 58522 +40
+ Misses 4898 4897 -1
- Partials 4114 4117 +3
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
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.
Part of #2195, item 3: a follow-up to #2213 and #2216.
At whole arguments, the compiled binomial, falling and rising factorials, double factorial and Catalan numbers are now evaluation's exact value, rounded once to a double.
The binomial took a whole lower argument as a product of ratios in doubles,
(n - i)/(i + 1), and each ratio was rounded. Sobinomial(54, 45)came out5317936259.999995where evaluation gives5317936260. Of the 2485 binomials with0 <= k <= n < 70, 1173 were not the integer. Now it usesbinomial(m, i + 1) = binomial(m, i) (m - i)/(i + 1), whose division leaves no remainder, over the shorter ofkandm - k. A negativengoes through(-1)^k binomial(k - n - 1, k).The factorial powers and the double factorial are products of whole factors, and were rounded at each step once a partial product passed
2^53. Each is now computed in doubles while every partial product is below2^53, where every step is exact, and inEIntegerpast it. The result is rounded byEFloat, or byERationalfor a negative order's reciprocal. A factor of0is checked for first, so a partial product past the range of the doubles stays past it, and the loop stops there.The Catalan numbers (#2216) were computed exactly but rounded by
(double)BigInteger, which truncates. 246 of the first 1000 came out a unit low in the last place:C_32 = 55534064877048200compiled to55534064877048190. They are rounded byEFloatnow. Nothing else in the library rounds aBigIntegerto a double for a result."binomial(x, 45)".ToEntity().Compile<double, double>("x")(54)5317936259.9999955317936260"binomial(x, 30)".ToEntity().Compile<double, double>("x")(60)1.1826458156486146E+171.1826458156486142E+17"catalannumber(x)".ToEntity().Compile("x").Call(32)(55534064877048190, 0)(55534064877048200, 0)"x!!".ToEntity().Compile("x").Call(-301)(2.6643404405685313E-307, 0)(2.6643404405685293E-307, 0)Each test compares FastExpression and the LINQ compiler with evaluation, as doubles and exactly:
10^12, and 58 whole second arguments from-12to45;2^53and past the doubles, among others at(60, 30),(1100, 550),(3000, 1500)and(-1, 4001);-301to320;0to1000.The expected value is the exact rational, rounded once by
ERational.ToNumericsgoes through a decimal whose exponent has a floor, and reads1/299!!as0. On master's kernel, 9 of these tests fail.The combinatorial entry in
BREAKING-CHANGES.md, unreleased, now says so and gains thebinomial(54, 45)row.🤖 Generated with Claude Code