Repository navigation
Compiling over the reals can refuse what is not real - #2297
Merged
Rafael-SOWNet merged 2 commits intoOct 31, 2026
Merged
Conversation
Compiled into a function returning double or float, every value computed on the way is real, so sin(arcsin(x)) at 2, which is 2, is NaN, as 1/x is at 0 where there is no value. That is the behaviour, and it is now written on every Compile overload. MathS.Settings.RefuseNonRealCompilation, off by default, refuses such an expression instead: with it on, an expression that cannot be shown real wherever it is defined throws UncompilableNodeException, so a NaN from the compiled function means only that there is no value. The showing is TreeAnalyzer.IsRealValued, with each argument written as one fresh variable, and it is conservative: sqrt(x) and ln(x) are refused too. The Complex compilers and statements are unaffected. IsRealValued now reads floor, ceil, round, min and max of real arguments as real, which the setting needs and which also answers the derivative of a modulus or a sign of one: d/dx abs(floor(x)) was left unevaluated. limit(sin(floor(x)) / x, x, +oo) is 0 again, as in 2.6.0: #2284 took away the l'Hopital route that had answered it. RefuseNonRealCompilationTest takes the default NaN, the refusals over double and float, what is real still compiled, a division by zero still NaN, and the Complex compiler and a statement unaffected. PublicApi.txt gains the setting. The suite, the trio, F#, AOT and the eight harnesses pass. Fixes #2286. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2297 +/- ##
==========================================
- Coverage 86.73% 86.72% -0.01%
==========================================
Files 310 310
Lines 67960 67973 +13
Branches 19740 19744 +4
==========================================
+ Hits 58944 58952 +8
- Misses 4884 4887 +3
- Partials 4132 4134 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
CompilationExtensions.cs and Compile.Linq.Definition.cs are generated from their .tt templates, and the remark had been written into the output only, so regenerating dropped it and Generated Files Up To Date failed. regenerate_all.sh now reproduces the committed files exactly. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Rafael-SOWNet
deleted the
a-real-compilation-can-refuse-what-is-not-real
branch
October 31, 2026 12:56
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This answers the question left on #2286. A function compiled to return
doubleorfloatcomputes every intermediate value as a real number. Sosin(arcsin(x))at 2, whose value is 2, comes out as NaN, just as1/xdoes at 0, where there is no value at all. That behaviour stays as it is, and it is now documented on everyCompileoverload.MathS.Settings.RefuseNonRealCompilation, off by default, refuses such an expression instead. With it on, an expression that can't be shown to be real wherever it is defined throwsUncompilableNodeException, so a NaN from the compiled function means only that there is no value. The check isTreeAnalyzer.IsRealValued, with every argument written as one fresh variable. It is conservative:sqrt(x)andln(x)are refused too. The compilers overComplex, and statements, are unaffected.IsRealValuednow also readsfloor,ceil,round,minandmaxof real arguments as real. Without that, the setting would refusefloor(x). The change also gives answers where the derivative of a modulus or a sign needs to know its argument is real:derivative(abs(floor(x)), x)0 provided not floor(x) = 0 and not x in ZZderivative(abs(min(x, 1)), x)sgn(min(x, 1)) * (1 - sgn(x - 1)) / 2 provided ...limit(sin(floor(x)) / x, x, +oo)0in 2.6.0, unevaluated on master since #22840RefuseNonRealCompilationTestcovers:doubleandfloatComplexcompiler and a statement left alonePublicApi.txtgains the setting. The setting's documented example runs underDocumentationExamplesRunTest. The suite (18,460), the trio, F#, AOT and the eight harnesses pass locally.Fixes #2286.
🤖 Generated with Claude Code