Skip to content

Divide a quotient of factorials before rounding it into the exponent range - #2338

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
a-quotient-of-factorials-past-the-exponent-range
Nov 3, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
a-quotient-of-factorials-past-the-exponent-range

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

A binomial, falling or rising factorial of an order that is not whole is a quotient of factorials, and each factorial was rounded into the evaluation's exponent range (it ends at 1e1000) before the quotient was taken.

Input 2.6.0 master This PR mpmath
binomial(450.5, 3.25) +oo +oo 50428864.5080... 50428864.5080...
binomial(2500.5, 3.25) NaN NaN 13324626798.1423... 13324626798.1423...
binomial(10000, 1.43) unevaluated NaN 414189.539... 414189.539...
binomial(479001600, 1.43) unevaluated does not finish, ignores cancellation 2042181498707.571..., 83 ms 2042181498707.571...
binomial(pi, 2000) NaN NaN 2.10439...E-14 2.10439...E-14
fallingfactorial(10000, 1.43) no such function NaN 524791.324... 524791.324...
  • The factorials are taken at the caller's precision with no bound on the exponent, divided, and only then rounded into the caller's context. Real arguments stay decimals throughout: as complex numbers each product added a zero imaginary part to a number with an exponent in the millions, which made binomial(10^7, 1.43) take over 20 s.
  • A decimal factorial is exact only within the cached factorials (up to 1000); past that Spouge's approximation takes it, as it already took anything past an int32. An exact 479001600! has four billion digits.
  • A whole k with a decimal n is built as binomial(n, i) one factor at a time, not as the falling factorial over k!.

Found by compilesweep, whose seed 13 stopped on binomial((2x)!, lambertw(0, x)) at x = 6. No issue was filed. The suite (18743), the five test projects and the eight harnesses pass, with 0 warnings. A BREAKING-CHANGES entry is included.

🤖 Generated with Claude Code

…range

A binomial, falling or rising factorial of an order that is not whole is a
quotient of factorials, and each factorial was rounded into the evaluation's
context, whose exponent ends at 1e1000. Past n of about 450 the numerator
overflowed and binomial(450.5, 3.25) was +oo; a little further both did,
and binomial(2500.5, 3.25) was NaN, where it is 13324626798.14. They are now
taken at the caller's precision with no bound on the exponent and divided
before the quotient is rounded. Real arguments stay decimals throughout: as
complex numbers, every product added a zero imaginary part to a number whose
exponent was in the millions, and binomial(10^7, 1.43) took over 20 s.

A whole n was computed as an exact factorial, so binomial(479001600, 1.43)
built a number of four billion digits and did not stop when cancelled; a
decimal factorial is now exact only within the cached factorials, and
Spouge's approximation takes the rest, as it took everything past an int32.
It is 2042181498707.57 in 83 ms.

A whole k with a decimal n was the falling factorial over k!, which
overflowed the same way: binomial(pi, 2000) was NaN, where it is 2.1e-14.
It is now built as binomial(n, i) one factor at a time.

Every value in the test is mpmath's at 50 digits. Found by compilesweep,
whose seed 13 stopped on binomial((2x)!, W(x)) at x = 6; no issue was
filed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rafael-SOWNet Rafael-SOWNet added this to the 2.7.0 milestone Nov 3, 2026
@Rafael-SOWNet Rafael-SOWNet moved this from Todo to In review in AngouriMath Nov 3, 2026
@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.60870% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.76%. Comparing base (77ed372) to head (f40caec).

Files with missing lines Patch % Lines
...nuous/Evaluation.Continuous.Arithmetics.Classes.cs 81.39% 2 Missing and 6 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2338      +/-   ##
==========================================
- Coverage   86.77%   86.76%   -0.02%     
==========================================
  Files         312      312              
  Lines       68563    68598      +35     
  Branches    19950    19962      +12     
==========================================
+ Hits        59498    59519      +21     
- Misses       4905     4914       +9     
- Partials     4160     4165       +5     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.30% <82.60%> (-0.02%) ⬇️
fsharp 32.97% <ø> (ø)
interactive 40.72% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...rces/AngouriMath/Functions/InternalAMExtensions.cs 85.60% <100.00%> (+0.05%) ⬆️
...nuous/Evaluation.Continuous.Arithmetics.Classes.cs 87.55% <81.39%> (-0.43%) ⬇️

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Rafael-SOWNet
Rafael-SOWNet merged commit 493b7ef into master Nov 3, 2026
35 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in AngouriMath Nov 3, 2026
@Rafael-SOWNet
Rafael-SOWNet deleted the a-quotient-of-factorials-past-the-exponent-range branch November 3, 2026 03:11
Rafael-SOWNet added a commit that referenced this pull request Nov 3, 2026
A Catalan number of a number that is not whole is 4^n Γ(n + 1/2) over
√π Γ(n + 2), and each gamma was computed in the evaluation's exponent
range. From n = 449.5, whose number is 2.5e266, both were +oo and the
quotient NaN, and catalannumber(-60.3), -8.4e-40, was NaN as well. The two
gammas are now one QuotientOfFactorials, as the binomial's are since
#2338, and for a real n the 4^n times it is formed in decimals with no
bound on the exponent and rounded at the end: a number made of 4^(1e20)
itself has an exponent near 6e19, which the downcasting cannot read as an
integer. Found by compilesweep, on catalannumber(Ei(sinh(x))) at 6.

And QuotientOfFactorials made its result as any number, which reads a
value under the downcasting tolerance as a cancellation's residual and
rounds it onto zero. A quotient cancels nothing: fallingfactorial(0.5,
-100.5), 9.4e-161, was 0, and risingfactorial(100.5, -60.5), 2.2e-111,
was 0. The quotient, and the falling factorial over k! beside it, are now
made at a zero scale.

None of the three functions is in 2.6.0, so there is no breaking entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant