Skip to content

Factorise past the longs, and decide IsPrime by Miller-Rabin - #2352

Merged
Rafael-SOWNet merged 2 commits into
masterfrom
factorize-past-the-longs
Nov 3, 2026
Merged

Rafael-SOWNet merged 2 commits into
masterfrom
factorize-past-the-longs

Conversation

@Rafael-SOWNet

@Rafael-SOWNet Rafael-SOWNet commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Closes #2341. Closes #2342.

2.6.0 and master now
MathS.NumberTheory.Factorize(2^64) OverflowException (2, 64)
"phi(7^30)".Simplify() OverflowException 19319434534879078361025642, 41 ms
(2^89 - 1).IsPrime OverflowException true
Factorize(9223372036854775783), the largest prime below 2^63 does not finish itself, 10 ms
phi(2^62) right, 2.1 s right, 0.11 s (cold)
Factorize(1000000007 * 1000000009) right, 1.3 s right, 74 ms
  • TryFactorize: trial division in EInteger up to 65536, bounded by what is left to factor rather than by the running totient. Then Primes.IsPrime (Primality is decided by Miller-Rabin and Lucas-Lehmer, and finishes #2232's Miller–Rabin and Lucas–Lehmer) is asked of the rest, and Pollard's rho splits a rest that is composite. A rest above 65536² with no factor below it is prime once proven so, or its two pieces are each past 65536.
  • phi, CountDivisors and Factorize are built on it. Where a factor is neither proven prime nor split (an undecided probable prime past ψ13, or a composite rho does not split within its budget), the public methods throw NotSufficientlySupportedException. phi(n) in an expression is left as written instead of throwing out of Simplify, as the issue asks.
  • Integer.IsPrime is Primes.IsPrime, as PP membership is. That is bool? internally. The public bool throws where primality is not decided, rather than becoming bool?, which would break the API. The two phi(p ^ k) rules (the matched one and the pattern) fire only where primality is proven.
  • The compiled totient over double, long and int had the same wrapping loop and now takes the same path. The long overload of Phi is gone; it had no caller left.

Tests: AFactorisationPastTheLongsTest, 24 cases, each expected value checked with sympy. 12 fail on master (four by the 30 s cap); the 12 small cases pass on both. The full suite, AOT and the nine harnesses pass. There is a BREAKING-CHANGES entry, measured on 2.6.0.

🤖 Generated with Claude Code

Factorize, CountDivisors and phi trial-divided over long, and IsPrime was
whether the divisor count was 2. Past 2^63 each threw OverflowException,
though the first division finds a factor like 2 or 7 at any size, and
Simplify folded phi(7^30) to an integer and threw. The loop ran while the
divisor's square was at most the running totient, not what was left to
factor, so 2^62 took 1.5e9 divisions after the first had divided every 2
out; and past 3037000499 the square wrapped negative, so the largest
prime below 2^63 never finished. 2.6.0 does all of this.

TryFactorize divides in EInteger as far as 65536, bounded by what is left,
asks Primes.IsPrime (Miller-Rabin and Lucas-Lehmer) of the rest, and
splits a composite rest by Pollard's rho. phi, the divisor count and
Factorize are built on it; where a factor is neither proven prime nor
split they throw NotSufficientlySupportedException, and phi(n) in an
expression is left as written. IsPrime is Primes.IsPrime, throwing where
primality is not decided, and the two phi(p^k) rules fire only where it is
proven. The compiled totient, over double and long, takes the same path:
its loop wrapped the same way.

Closes #2341
Closes #2342

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 74.66667% with 19 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.75%. Comparing base (0731fc1) to head (4422073).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
...rces/AngouriMath/Functions/InternalAMExtensions.cs 74.19% 6 Missing and 10 partials ⚠️
...Continuous/Entity.Continuous.Integer.Definition.cs 50.00% 0 Missing and 1 partial ⚠️
...Math/Core/Transformations/Matching/MatchedRules.cs 0.00% 0 Missing and 1 partial ⚠️
...Evaluation.Discrete/Evaluation.Discrete.Classes.cs 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2352      +/-   ##
==========================================
- Coverage   86.78%   86.75%   -0.04%     
==========================================
  Files         312      312              
  Lines       68675    68760      +85     
  Branches    19988    20025      +37     
==========================================
+ Hits        59602    59655      +53     
- Misses       4905     4921      +16     
- Partials     4168     4184      +16     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.30% <74.66%> (-0.04%) ⬇️
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 Δ
...nctions/Algebra/Polynomials/PolynomialFactoring.cs 98.31% <100.00%> (ø)
...h/Functions/Compilation/IntoLinq/MathAllMethods.cs 74.74% <100.00%> (ø)
...s/Simplification/Patterns/Patterns.NumberTheory.cs 100.00% <100.00%> (ø)
Sources/AngouriMath/Numerics/SpecialFunctions.cs 80.97% <100.00%> (+0.08%) ⬆️
...Continuous/Entity.Continuous.Integer.Definition.cs 80.39% <50.00%> (-1.61%) ⬇️
...Math/Core/Transformations/Matching/MatchedRules.cs 99.55% <0.00%> (-0.03%) ⬇️
...Evaluation.Discrete/Evaluation.Discrete.Classes.cs 89.59% <66.66%> (-0.21%) ⬇️
...rces/AngouriMath/Functions/InternalAMExtensions.cs 83.69% <74.19%> (-1.92%) ⬇️

... and 9 files with indirect coverage changes

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

MathAllMethods.cs is generated from MathAllMethods.tt, and the Regenerate
job rebuilt it with the long overload calling the long Phi this branch
removed. The template now writes what the generated file already has.

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

Copy link
Copy Markdown
Member

These should definitely be queued for v3 (all API insufficiencies like these need to be queued for v3)

@Rafael-SOWNet

Copy link
Copy Markdown
Member Author

Queued in #1019, item 18. Integer.IsPrime becomes bool?, null where Miller–Rabin and Lucas–Lehmer leave it open. Factorize, CountDivisors and Phi return null where a factor is neither proven prime nor split, which is #1569's rule. Until v3, this PR throws NotSufficientlySupportedException in those places, so the bool stays as it is.

🤖 Generated with Claude Code

@Rafael-SOWNet
Rafael-SOWNet merged commit ba63f2f into master Nov 3, 2026
42 of 45 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 factorize-past-the-longs branch November 3, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

2 participants