Skip to content

The factorial, gamma and the totient compile under Compile<TIn, TOut> - #1620

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
factorial-and-phi-compile
Sep 30, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
factorial-and-phi-compile

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

The other half of #1607: x!, gamma and phi under Compile<TIn, TOut>, which had no form for them. Compile had one, and it had defects of its own.

  • The factorial. Both compilers now call one routine in SpecialFunctions:

    • at a whole number up to 170, the exact factorial rounded once to a double;
    • past 170, where a double cannot hold it, infinity;
    • at a negative whole number, one of the gamma function's poles, NaN, as in the interpreter;
    • elsewhere, the Lanczos approximation Compile has always used (g = 7, nine terms), taken in logarithms, the reflection formula included.

    Compile's factorial overflowed its own power before the value did. From just past 141!, about 2e243, it compiled to NaN, up to 170!. At a whole number it was a rounding off the integer, 23.999999999999996 at 4, which a compilation over integers would truncate to 23. Off the real line the reflection's sin(pi z) overflowed where the value is tiny, and gave NaN; it is now a logarithm written out past |Im(pi z)| = 20. gamma(x) is (x - 1)! and needs nothing of its own.

  • The totient. At a whole number it is the totient, and 0 at one that is not positive, as the interpreter has it. At any other number it is NaN, as the interpreter's is. Compile truncated a fraction to the whole number below it, so phi(2.5) was phi(2), which is 1. Under Compile<TIn, TOut>, long, int and BigInteger take it exactly.

Measured against mpmath, the compiled factorial is within 1.1e-13 of the value on a grid of [-14, 14]^2, within 2.4e-13 up the imaginary axis to 10^4.5, and within 3.2e-13 on circles out to radius 300. The error is larger only where the conditioning forces it: next to a pole, and in the subnormal range past -177, where a double holds few digits of the value.

Measured

  • SpecialFunctionCompilationTest gains:
    • the factorial and gamma against the interpreter, through both compilers and over doubles;
    • whole numbers exact, including under Compile<long, long>;
    • 171 infinite, and the poles NaN;
    • the totient at whole numbers over every integer type, and NaN elsewhere.
  • UserInvalidExceptions: phi, gamma and the factorials compile now. The theory of nodes with no compiled form is binomial, gcd, lcm and prime.
  • BREAKING-CHANGES.md: each changed answer, as measured on 2.5.0.
  • The library builds for every target with no warnings, and the unit tests pass: 14,091, none failed (net10.0).
  • The performance gate passes on f6c5ca5. Allocation matches the baseline on all 19 gated benchmarks, and the compiled functions' runs (RunEasy, RunMedium, RunHard) still allocate nothing and take the same time.

Closes #1607.

🤖 Generated with Claude Code

Compile<TIn, TOut> had no form for x!, gamma or phi, and Compile's own had defects. Both compilers
now call one routine in SpecialFunctions.

The factorial is exact at a whole number up to 170, rounded once to a double, and infinite past it;
NaN at a negative whole number, one of the gamma function's poles, as in the interpreter; and
elsewhere the Lanczos approximation Compile always used (g = 7, nine terms), taken in logarithms,
the reflection formula included. Compile's overflowed its own power before the value did, so from
just past 141!, about 2e243, it compiled to NaN, up to 170!. At a whole number it was a rounding
off the integer, 23.999999999999996 at 4, which a compilation over integers truncates to 23. Off
the real line the reflection's sin(pi z) overflowed where the value is tiny; past
|Im(pi z)| = 20 it is a logarithm written out now. gamma(x) is (x - 1)!.

The totient is the totient at a whole number, 0 at one that is not positive, and NaN at any other
number, as the interpreter's is. Compile truncated a fraction to the whole number below it, so
phi(2.5) was phi(2). Under Compile<TIn, TOut>, long, int and BigInteger take it exactly.

Against mpmath the compiled factorial is within 1.1e-13 of the value on a grid of [-14, 14]^2,
2.4e-13 up the imaginary axis to 10^4.5 and 3.2e-13 on circles out to radius 300. It is further
out only where the conditioning forces it: next to a pole, and in the subnormal range past -177.

SpecialFunctionCompilationTest gains the factorial and gamma against the interpreter, through both
compilers and over doubles; whole numbers exact, including under Compile<long, long>; 171 infinite
and the poles NaN; and the totient at whole numbers over every integer type, NaN elsewhere.
UserInvalidExceptions keeps binomial, gcd, lcm and prime as the nodes with no compiled form.

Closes #1607.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Rafael-SOWNet Rafael-SOWNet added this to the 2.6.0 milestone Sep 30, 2026
@Rafael-SOWNet
Rafael-SOWNet merged commit 58a75c7 into master Sep 30, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The special functions have no compiled form, and neither do x!, gamma and phi under Compile<TIn, TOut>

1 participant