Skip to content

Compute a large factorial as a balanced product, and keep only the small ones - #2329

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
a-large-factorial-is-a-product-tree-and-is-not-kept
Nov 2, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
a-large-factorial-is-a-product-tree-and-is-not-kept

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Following up Happypig375's comment on #2327 about the speed and memory of large modulo operations. The first cost there was the factorial itself.

Every factorial up to the largest one asked for was cached, each built from the one before by multiplying the whole running product by one more factor. Now:

  • factorials up to 1000! are still cached, half a megabyte in all;
  • past that, the factorial is a balanced product tree in System.Numerics.BigInteger, and it is not kept.
master this PR
(10^5)! mod 1000003 21 s, 13.7 GB allocated 0.11 s, 8.8 MB
20000!, allocated 276 MB 1.2 MB
heap after (10^5)! and a full GC 8.6 GB 3 MB

The same tree in EInteger takes 0.44 s and 453 MB for 1 · 2 ⋯ 10^5; in BigInteger it takes 0.1 s and 7 MB, and the conversion back takes 2 ms. No answer changes.

Tests: ALargeFactorialTest checks factorials on both sides of the cache bound against an independent product, and checks (10^5)! mod 1000003 against Python. It also asserts that 20000! allocates under 20 MB; that fails on master, at 306 MB.

A remainder of a large power or factorial is still computed from the whole number. A separate PR follows for that.

🤖 Generated with Claude Code

…all ones

Every factorial up to the largest one asked for was kept, each made from
the one before by multiplying the whole running product by one more
factor. (10^5)! took 21 s, allocated 12.9 GB, and left 8.6 GB on the heap
after a full collection, for the rest of the process.

Factorials up to 1000! are still cached (half a megabyte in all). Past
that the factorial is a balanced product tree in System.Numerics.BigInteger,
which multiplies large numbers subquadratically, and is not kept:

| | before | after |
|---|---|---|
| (10^5)! mod 1000003 | 21 s, 13.7 GB | 0.11 s, 8.8 MB |
| 20000!, allocated | 276 MB | 1.2 MB |
| heap after (10^5)!, after a full GC | 8.6 GB | 3 MB |

The same tree in EInteger took 0.44 s and 453 MB for 1 2 ... 10^5;
BigInteger takes 0.1 s and 7 MB, and the conversion back is 2 ms.

#2327 (comment)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.75%. Comparing base (93a52f0) to head (8c71606).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2329   +/-   ##
=======================================
  Coverage   86.75%   86.75%           
=======================================
  Files         312      312           
  Lines       68447    68456    +9     
  Branches    19909    19912    +3     
=======================================
+ Hits        59379    59390   +11     
+ Misses       4908     4907    -1     
+ Partials     4160     4159    -1     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.30% <100.00%> (+<0.01%) ⬆️
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.55% <100.00%> (+0.24%) ⬆️

... and 4 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 8a8ed24 into master Nov 2, 2026
35 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in AngouriMath Nov 2, 2026
@Rafael-SOWNet
Rafael-SOWNet deleted the a-large-factorial-is-a-product-tree-and-is-not-kept branch November 2, 2026 13:50
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