Skip to content

Membership and divisibility compile - #2223

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
membership-and-divisibility-compile
Oct 30, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
membership-and-divisibility-compile

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Part of #2195, item 3: the last of its statements.

x in S and a divides b were refused by both compilers. Each now compiles to the truth value evaluation gives: 1, 0 or NaN in FastExpression, and true, false or null in the LINQ compiler.

Membership. The set is fixed when the expression is compiled, so only the element is computed. Before either compiler sees a membership, CompiledMembership rewrites it into the statement it makes about its element:

set becomes
union, intersection, difference Kleene's or, and, and and not of the sides' memberships, as evaluation decides them since #2221
interval Im(x) = 0 and the two comparisons with the ends; a number that is not real is in no interval, so i in [0; 1] is False
finite set equality with one of its members
conditional set its predicate of the element
RR, CC, ZZ, ZZ+, ZZ*, PP NumberStatements.In, through a new FastExpression instruction CALL_MEMBER whose reference names the set, and a method call in LINQ

NumberStatements.In has no truth value at NaN. An infinity is in RR and CC, as evaluation holds it until #2220 is decided, and in none of the sets of whole numbers. Primality is the interpreter's trial division, and is left open past 2^63, where the interpreter leaves it.

QQ stays refused: every finite double is a rational, while pi in QQ is False. BB stays refused too, and so does any set with one of those inside it.

Divisibility is NumberStatements.Divides, through CALL_DIVIDES in FastExpression. Between whole numbers it is whether the remainder is 0, with 0 dividing only 0. A double's remainder is exact however large the numbers are. Anywhere else it has no truth value, as evaluation gives NaN for 2 divides 5/2.

2.6.0 now
"x in [0; 1]".ToEntity().Compile("x").Call(0.5) UncompilableNodeException (1, 0)
"x in PP".ToEntity().Compile<Complex, bool?>("x")(7) UncompilableNodeException true
"3 divides x".ToEntity().Compile("x").Call(6) UncompilableNodeException (1, 0)
"3 divides x".ToEntity().Compile<double, bool?>("x")(2.5) UncompilableNodeException null

Tests. MembershipCompilationTest compares both compilers with evaluation:

  • 21 sets at 20 points, among them i, 1 + i, 2i, +oo and -oo;
  • divisibility on a 10 by 9 grid, including 10^20, 5/2, 2i and +oo;
  • memberships inside an Iverson bracket, a piecewise and connectives;
  • the refusals.

The piecewise case leaves out infinities, because a compiled -x at +oo has a NaN imaginary part. That is #2222, which predates this PR. Full suite 18011/0, interactive trio, AOT smoke 73/0 with a membership case, all frameworks build.

🤖 Generated with Claude Code

x in S and a divides b were refused by both compilers. Each now compiles
to the truth value evaluation gives: 1, 0 or NaN in FastExpression, and
true, false or null in the LINQ compiler.

The set is fixed when the expression is compiled, so only the element is
computed. CompiledMembership rewrites a membership, before either compiler
sees it, into the statement it makes about its element:
- a union, an intersection and a difference become Kleene's or, and, and
  and-not of the memberships in their sides, as evaluation decides them
  since #2221;
- an interval becomes the element's imaginary part being 0 and the two
  comparisons with its ends, since a number that is not real is in no
  interval, and i in [0; 1] is False rather than undecided;
- a finite set becomes an equality with one of its members;
- a conditional set becomes its predicate of the element.

A membership in RR, CC, ZZ, ZZ+, ZZ* or PP is left for each compiler,
which calls NumberStatements.In: a new FastExpression instruction,
CALL_MEMBER, whose reference names the set, and a method call in LINQ.
It has no truth value at NaN. An infinity is in RR and CC, as evaluation
holds it until #2220 is decided, and in none of the sets of whole numbers.
Primality comes from Primes.IsPrime, the interpreter's trial division, and
is left open past 2^63, where the interpreter leaves it.

QQ stays refused, because every finite double is a rational while
pi in QQ is False. BB stays refused too. So does any set with one of those
inside it.

Divisibility is NumberStatements.Divides, through CALL_DIVIDES in
FastExpression. Between whole numbers it is whether the remainder is 0,
with 0 dividing only 0, and a double's remainder is exact however large.
It has no truth value anywhere else, as evaluation gives NaN for
2 divides 5/2.

MembershipCompilationTest compares both compilers with evaluation:
- 21 sets at 20 points, among them i, 1 + i, 2i, +oo and -oo;
- divisibility on a 10 by 9 grid, with 10^20, 5/2, 2i and +oo;
- memberships inside an Iverson bracket, a piecewise and connectives;
- the refusals.
Infinities are left out of the piecewise case, since a compiled -x at +oo
has a NaN imaginary part. That is #2222, and it predates this change.

Part of #2195.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Rafael-SOWNet Rafael-SOWNet moved this from Todo to In review in AngouriMath Oct 30, 2026
@codecov

codecov Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.13483% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.67%. Comparing base (007a362) to head (696b7eb).

Files with missing lines Patch % Lines
...gouriMath/Functions/Compilation/IntoFE/Compiler.cs 76.92% 3 Missing ⚠️
Sources/AngouriMath/Numerics/NumberStatements.cs 90.00% 1 Missing and 2 partials ⚠️
...riMath/Functions/Compilation/CompiledMembership.cs 94.73% 0 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2223      +/-   ##
==========================================
+ Coverage   86.65%   86.67%   +0.01%     
==========================================
  Files         306      308       +2     
  Lines       67550    67639      +89     
  Branches    19588    19610      +22     
==========================================
+ Hits        58538    58623      +85     
  Misses       4897     4897              
- Partials     4115     4119       +4     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.22% <92.13%> (+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 Δ
...ath/Functions/Compilation/IntoFE/FastExpression.cs 96.72% <100.00%> (+0.07%) ⬆️
...ctions/Compilation/IntoLinq/CompilationProtocol.cs 91.29% <100.00%> (+1.21%) ⬆️
...Functions/Compilation/IntoLinq/IntoLinqCompiler.cs 96.82% <100.00%> (+0.39%) ⬆️
...riMath/Functions/Compilation/CompiledMembership.cs 94.73% <94.73%> (ø)
...gouriMath/Functions/Compilation/IntoFE/Compiler.cs 85.29% <76.92%> (-0.03%) ⬇️
Sources/AngouriMath/Numerics/NumberStatements.cs 90.00% <90.00%> (ø)

... and 7 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 commented Oct 30, 2026 •

Copy link
Copy Markdown
Member Author

The chain's CrashCheck changed from 2296 returned and 154 declined to 2294 and 156.

The two cases that moved are compile on x in ZZ and on x divides 2. CrashCheck compiles to a double result and catches UncompilableNodeException. On master, both stopped there. Now they compile, and the conversion of a statement to a double throws InvalidProtocolProvided. x > 1 has thrown the same since before 2.6.0. That conversion gap is filed as #2224. Nothing crashed. Both cases "returned" before only because their refusal was caught, and nothing that compiled before is refused now.

🤖 Generated with Claude Code

@Rafael-SOWNet
Rafael-SOWNet merged commit 5c6a13f into master Oct 30, 2026
36 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in AngouriMath Oct 30, 2026
@Rafael-SOWNet
Rafael-SOWNet deleted the membership-and-divisibility-compile branch October 30, 2026 04:58
Rafael-SOWNet added a commit that referenced this pull request Oct 30, 2026
Over System.Numerics.Complex, in FastExpression and in the LINQ compiler,
a product's imaginary part is a.Re b.Im + a.Im b.Re. With a real
infinity that is inf * 0, which is NaN. So -x at +oo was (-inf, NaN),
and so were 2 * x, x / 2 and x * x. That is a value with no imaginary
part at all, so a comparison of it had no truth value and a piecewise
passed over it. Evaluation gives -oo, and so does the compiler over
double.

RealProducts.Product and Quotient take two numbers whose imaginary parts
are both 0 as reals, and anything else as before. FastExpression's
CALL_MUL and CALL_DIV call them, and so does the LINQ compiler's
Multiply and Divide over Complex. A division by 0 is left to Complex,
whose NaN is evaluation's. A real Quotient would have made 1/x at 0
+inf, where evaluation has no value for 1/0.

MembershipCompilationTest's piecewise case, which #2223 kept away from
the infinities for this, now runs at +oo and -oo as well.

RealProductCompilationTest: 8 expressions at +oo or -oo, all failing on
master, and 6 elsewhere that keep their values: a division by 0, and
complex products and quotients.

A power at a real infinity is NaN in both parts, which is a different
mechanism, Complex.Pow. It is #2225.

Fixes #2222.

Co-Authored-By: Claude Opus 5.5 (1M context) <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