Repository navigation
Open
Open
Copy link
Milestone
Description
A harness, compilecheck, compiles a sample of every node that has a numeric or boolean value through both compilers, calls it at sample points, and compares the result with Substitute then EvalNumerical. Measured on master ea08214. Every compiled value agrees with EvalNumerical. What is missing are nodes that are refused.
| compiler | compiles |
|---|---|
FastExpression, Compile("x") |
43 of 71 numeric nodes, and 0 of 12 boolean |
LINQ, Compile<Complex, Complex> |
42 of 71 |
LINQ, Compile<double, double> |
44 of 71 |
LINQ, Compile<double, bool> |
10 of 12 boolean |
What is missing, grouped by what it would take:
- FastExpression has no booleans and no branch. So
piecewise,provided,iversonand every comparison are refused. The fix needs comparison and connective instructions that push 1 or 0, and a select instruction. The instructions run in a singleforeach, so a jump would also need an indexed loop. A comparison of a value that is not real should come out false, so thatx provided x > 0is NaN ati, asEvalNumericalhas it. - LINQ over
Complexrefuses comparisons. The message isThe binary operator GreaterThan is not defined for the types 'System.Numerics.Complex'. Sopiecewiseandprovidedcompile overdoublebut not overComplex, andmodfails the same way. A fix would compile a comparison of complex operands as a comparison of real parts when both operands are real, and as false otherwise. - These nodes have no compiled form in either compiler:
conj,arg,ReandIm: oneSystem.Numerics.Complexcall each.iverson: a conditional in LINQ.binomial,fallingfactorial,risingfactorial,n!!,gamma(a, z)andpolygamma: these need numerical implementations overdoubleandComplex.- The integer functions
prime,valuation,gcd,lcm,mobius,divisorsigma,primenu,primeomega,primepianddivides, and membershipx in [0; 1]. These could compile overdoubleat whole numbers and give NaN elsewhere, or stay refused.
- The calculus nodes and binders are refused by both:
derivative, the definiteintegral,limit,sum,productandapply(lambda(…)). Compilingexpr.Evaledfirst gives the computed form. WhetherCompileshould do that itself is a decision, because it would make compiling as slow as evaluating.
The full table
| node | sample | FastExpression | LINQ Complex |
LINQ double |
|---|---|---|---|---|
Variable |
x |
ok | ok | ok |
Integer |
3 |
ok | ok | ok |
Rational |
1/2 |
ok | ok | ok |
Real (root is Rational) |
0.5 |
ok | ok | ok |
Complex (root is Sumf) |
2 + 3i |
ok | ok | refused |
Constant |
pi |
ok | ok | ok |
Sumf |
x + 3 |
ok | ok | ok |
Minusf |
x - (x^2) |
ok | ok | ok |
Mulf |
x * (x + 1) |
ok | ok | ok |
Divf |
x / (x + 2) |
ok | ok | ok |
Powf |
x ^ 3 |
ok | ok | ok |
Logf |
log(2, x) |
ok | ok | ok |
Sinf |
sin(x) |
ok | ok | ok |
Cosf |
cos(x) |
ok | ok | ok |
Tanf |
tan(x) |
ok | ok | ok |
Cotanf |
cotan(x) |
ok | ok | ok |
Secantf |
sec(x) |
ok | ok | ok |
Cosecantf |
cosec(x) |
ok | ok | ok |
Arcsinf |
arcsin(x) |
ok | ok | ok |
Arccosf |
arccos(x) |
ok | ok | ok |
Arctanf |
arctan(x) |
ok | ok | ok |
Arccotanf |
arccotan(x) |
ok | ok | ok |
Arcsecantf |
arcsec(x) |
ok | ok | ok |
Arccosecantf |
arccosec(x) |
ok | ok | ok |
Absf |
abs(x) |
ok | ok | ok |
Signumf |
sgn(x) |
ok | ok | ok |
Conjugatef |
conj(x) |
refused | refused | refused |
Argf |
arg(x) |
refused | refused | refused |
Ref |
Re(x) |
refused | refused | refused |
Imf |
Im(x) |
refused | refused | refused |
Floorf |
floor(x) |
ok | ok | ok |
Ceilf |
ceil(x) |
ok | ok | ok |
Roundf |
round(x) |
ok | ok | ok |
Modf |
x mod 3 |
ok | refused | ok |
Maxf |
max(x, 1) |
ok | ok | ok |
Minf |
min(x, 1) |
ok | ok | ok |
Factorialf |
x! |
ok | ok | ok |
DoubleFactorialf |
x!! |
refused | refused | refused |
Binomialf |
binomial(x, 3) |
refused | refused | refused |
FallingFactorialf |
fallingfactorial(x, 3) |
refused | refused | refused |
RisingFactorialf |
risingfactorial(x, 3) |
refused | refused | refused |
IncompleteGammaf |
gamma(2, x) |
refused | refused | refused |
Polygammaf |
polygamma(1, x) |
refused | refused | refused |
Erff |
erf(x) |
ok | ok | ok |
Erfcf |
erfc(x) |
ok | ok | ok |
Erfif |
erfi(x) |
ok | ok | ok |
Eif |
Ei(x) |
ok | ok | ok |
Lif |
li(x) |
ok | ok | ok |
Sif |
Si(x) |
ok | ok | ok |
Cif |
Ci(x) |
ok | ok | ok |
Shif |
Shi(x) |
ok | ok | ok |
Chif |
Chi(x) |
ok | ok | ok |
Phif |
phi(x) |
ok | ok | ok |
Primef |
prime(x) |
refused | refused | refused |
Valuationf |
valuation(x, 2) |
refused | refused | refused |
Gcdf |
gcd(x, 4) |
refused | refused | refused |
Lcmf |
lcm(x, 4) |
refused | refused | refused |
Mobiusf |
mobius(x) |
refused | refused | refused |
DivisorSigmaf |
divisorsigma(1, x) |
refused | refused | refused |
PrimeNuf |
primenu(x) |
refused | refused | refused |
PrimeOmegaf |
primeomega(x) |
refused | refused | refused |
PrimePif |
primepi(x) |
refused | refused | refused |
Iversonf |
iverson(x > 0) |
refused | refused | refused |
Providedf |
x provided x > 0 |
refused | refused | ok |
Piecewise |
piecewise(x provided x > 0, -x provided x <= 0) |
refused | refused | ok |
Derivativef |
derivative(x^3, x) |
refused | refused | refused |
Integralf |
integral(t x, t, 0, 1) |
refused | refused | refused |
Limitf |
limit(sin(t x)/t, t, 0) |
refused | refused | refused |
Summationf |
sum(k x, k, 1, 3) |
refused | refused | refused |
Productf |
product(x + k, k, 1, 3) |
refused | refused | refused |
Application |
apply(lambda(t, t^2), x) |
refused | refused | refused |
| node | sample | FastExpression | LINQ double -> bool |
|---|---|---|---|
Equalsf |
x = 2.5 |
refused | ok |
Greaterf |
x > 1 |
refused | ok |
GreaterOrEqualf |
x >= 1 |
refused | ok |
Lessf |
x < 1 |
refused | ok |
LessOrEqualf |
x <= 1 |
refused | ok |
Andf |
x > 0 and x < 2 |
refused | ok |
Orf |
x < 0 or x > 2 |
refused | ok |
Xorf |
x > 0 xor x > 1 |
refused | ok |
Notf |
not x > 0 |
refused | ok |
Impliesf |
x > 0 -> x > 1 |
refused | ok |
Dividesf |
3 divides x |
refused | refused |
Inf |
x in [0; 1] |
refused | refused |
Related: #2145 and #2182, which added most of the nodes in item 3.
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
- StatusShow more project fieldsTodo
Activity
The conjugate, the argument, the parts and the Iverson bracket compile (
Rafael-SOWNet commentedon Oct 29, 2026
Done in #2196:
conj,arg,ReandImcompile in both compilers, andiversoncompiles underCompile<TIn, TOut>over the reals. FastExpression now covers 47 of 71 nodes and LINQ overComplex46, with no disagreements.Item 2 is not just a matter of comparing real parts. The interpreter has no truth value for
i > 1: a comparison of a non-real number is undecided, and aprovidedorpiecewisewhose predicate is undecided has no value. A plainboolcan only say false. That makesx provided x > 1NaN ati, which is right, butnot (x > 1)true ati, which is wrong.Comparisons over
Complextherefore need three-valued logic:bool?with Kleene's tables;providedandpiecewisegive NaN where the predicate is nottrue.The compiled booleans over
doublehave the same gap at a NaN argument, where .NET's comparisons are false.A piecewise passes over a case with no truth value
A compiled statement with no truth value has none (#2208)
FastExpression compiles statements, provided and piecewise (#2209)
Rafael-SOWNet commentedon Oct 29, 2026
Items 1 and 2 are in.
Complexcompiles: it holds or fails where both sides are real, and isnullwhere one isNaNor not real. Overdoublea comparison withNaNisnulltoo, where it was false, sonot (x > 1)is no longer true atNaN. The connectives follow Kleene's tables. Aprovidedhas no value where its predicate has none, and apiecewisepasses over such a case, as evaluation does. Asboolthe result isfalse, and asbool?it isnull.provided,piecewiseand Iverson brackets. A statement is1,0orNaNon the stack, and the comparisons and connectives are the LINQ compiler's. There is no jump: every case of apiecewiseis computed and the one that holds is kept.Both are checked against evaluation over a grid of expressions and of points,
iandNaNamong them.Next:
modoverComplexin LINQ, through the remainder FastExpression already takes. Then item 3's numerical nodes, starting withbinomial. Measuring it turned upbinomial(3, 1/2), which evaluation leaves unevaluated where the gamma ratio gives32/(5 pi); that is fixed separately.🤖 Generated with Claude Code
https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
Compile mod over Complex in the LINQ compiler (#2210)
The combinatorial functions compile (#2213)
The Lambert W function compiles, and W_0 left of -2/e is on its branch (
The polygamma functions and the harmonic numbers compile (#2215)
The Catalan numbers compile (#2216)
The number-theoretic functions compile (#2217)
Rafael-SOWNet commentedon Oct 30, 2026
Item 3, the numerical nodes. Each compiles in both compilers, over
Complexand overdouble, and is checked against evaluation at a grid of points:modoverComplexin LINQ, by FastExpression's remainder: the floored one where both sides are real,NaNwhere either is notbinomial,fallingfactorial,risingfactorialandn!!lambertw(k, z)polygamma(n, z)andharmonicnumber(n, m)catalannumbermobius,divisorsigma,primenu,primeomega,valuation,primeandprimepi: exact at a whole argument andNaNat any otherlambertw,harmonicnumberandcatalannumberwere not in the issue's table.Measuring the binomial found two evaluation defects, fixed separately in #2211 and #2212:
binomial(3, 1/2)was left unevaluated; it is32/(5 pi).binomial(1/2, 3/2), was left as written; it is0.Checking the Lambert W kernel against mpmath found a third, fixed in #2214. Evaluation and the kernel shared one start, which put
W_0on the wrong branch on the real axis between-1and-2/e, where it came out real, and near-1.Still refused, by decision:
gamma(a, z). For a rationalawith an odd denominator, evaluation takes the real root on the negative axis. A compiledaarrives as a double, so1/3cannot be told from a decimal near it. The series also needs guard digits that a double does not have. A compiled form would disagree with evaluation.gcdandlcm. Evaluation takes them over the rationals, and every finite double is a rational. A compiledgcd(0.1, 1)would be exact for the double nearest0.1and meaningless for0.1. They could compile at whole arguments only, withNaNelsewhere; that is not decided yet.Item 4, the calculus nodes and binders, is untouched.
🤖 Generated with Claude Code
Compiled combinatorial functions at whole arguments are exact (#2218)
Membership and divisibility compile (#2223)
A congruence compiles (#2233)
A quantifier, a subset and a cardinality over a finite set compile (#…
Rafael-SOWNet commentedon Oct 30, 2026
Since the last note:
(double)BigInteger, which truncates1,0orNaN, in the LINQ compiler too; it threwInvalidProtocolProvidedsin(x > 1), is refused by both compilers; FastExpression answered it, and LINQ threwKeyNotFoundException-xat+oowas(-∞, NaN), andx^2at+oowas(NaN, NaN)Measuring these turned up three defects in evaluation:
Falsewhere one side could not decide it.2^63from an overflow in the trial division. It is now Miller–Rabin and Lucas–Lehmer.+oobeing a member ofRRandCC, is not fixed. It moved to v3 with Pending breakages: changes agreed or arguable that cannot ship before a major version #1019 §15.work/compilecheck, regenerated on master b8a6a6f, finds no compiled value that disagrees with evaluation:Complexand 65 overdouble;Still refused:
gamma(a, z), as explained in the last note.Two decisions remain:
gcdandlcm. Evaluation takes them over the rationals, and every finite double is a rational, so a compiledgcd(0.1, 1)would be exact for the double nearest0.1and meaningless for0.1. Should they compile at whole arguments only, withNaNelsewhere, or stay refused?derivative, the definiteintegral,limit,sum,productandapply(lambda(…)). Compilingexpr.Evaledgives the computed form. ShouldCompiledo that itself, at the cost of compiling as slowly as evaluating, or keep refusing, so that the caller decides?🤖 Generated with Claude Code