Skip to content

A compiled function takes the side of its branch cut evaluation takes - #2240

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
a-compiled-zero-is-unsigned
Oct 30, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
a-compiled-zero-is-unsigned

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Fixes #2236. Fixes #2239. Both were found by work/compilesweep.

The branch cuts (#2236). System.Numerics.Complex computes -0 as a part of many real values: cos(2) is (cos 2, -sin 2 · sinh 0), which is (-0.416, -0), and conj(-2) is (-2, -0). Complex.Log, Complex.Sqrt and the inverse functions read a -0 as the lower side of the negative real axis. The library has no signed zero, so a real number is on the upper side. So in both compilers ln(cos(x)) at 2 was -0.8767 - pi i, where evaluation gives -0.8767 + pi i, and sqrt(conj(x)) at -4 was -2i.

ComplexBranches.Unsigned reads each zero part as +0, by adding +0.0, which turns -0 into +0 and changes no other number. It is taken at the entry of every compiled function with a cut, in FastExpression and in MathAllMethods:

  • the logarithm;
  • a power that is not whole, in RealProducts.Power;
  • arcsin, arccos, arctan, arccotan, arcsec and arccosec;
  • arg;
  • the exponential and logarithmic integrals;
  • lambertw.

ComplexBranches.Arcsin already conjugated on its cut. It now does so from the +0 side, which is the case it was written for.

The logarithm's base (#2239). FastExpression's logarithm was Complex.Log(value, base.Real), whose base parameter is a double, so a complex base lost its imaginary part: log(x, 2) at 1 + i was NaN. It is now ComplexBranches.Log, ln(value) / ln(base), which is how the LINQ compiler already took it.

2.6.0 and master now
"ln(cos(x))".ToEntity().Compile("x").Call(2) (-0.8767, -3.1416) (-0.8767, 3.1416)
"log(x, 2)".ToEntity().Compile("x").Call(new Complex(1, 1)) (NaN, NaN) (0.3260, -0.7387)

Tests. BranchCutCompilationTest takes each of the 19 functions at 11 real points, with its argument written three ways that land on a cut: conj(x), cos(x) and i * x. It compares both compilers with evaluation, and adds three logarithms to complex bases. 9 of its 22 cases fail on master. Two kinds of point are left out:

  • a pole, where the infinity has a NaN part, which is not what this test is about;
  • an exponent with an odd denominator, where evaluation takes the real root, which a double exponent cannot show.

Full suite 18135/0, interactive trio, AOT smoke 73/0, all frameworks build.

🤖 Generated with Claude Code

System.Numerics.Complex computes -0 as a part of many real values.
cos(2) is (cos 2, -sin 2 * sinh 0), which is (-0.416, -0), and
conj(-2) is (-2, -0). Complex.Log, Complex.Sqrt and the inverse
functions read a -0 as the lower side of the negative real axis. The
library has no signed zero, so a real number is on the upper side. So in
both compilers, ln(cos(x)) at 2 was -0.8767 - pi i where evaluation gives
-0.8767 + pi i, and sqrt(conj(x)) at -4 was -2i.

ComplexBranches.Unsigned reads each zero part as +0, by adding +0.0,
which turns -0 into +0 and changes no other number. It is taken at the
entry of every compiled function with a cut, in FastExpression and in
MathAllMethods:
- the logarithm;
- a power that is not whole, in RealProducts.Power;
- arcsin, arccos, arctan, arccotan, arcsec and arccosec;
- arg;
- the exponential and logarithmic integrals;
- lambertw.
ComplexBranches.Arcsin already conjugated on its cut, and now does so
from the +0 side, which is what it was written for.

FastExpression's logarithm was Complex.Log(value, base.Real), whose base
parameter is a double, so a complex base lost its imaginary part:
log(x, 2) at 1 + i was NaN. It is ComplexBranches.Log now,
ln(value) / ln(base), as the LINQ compiler already took it (#2239).

BranchCutCompilationTest takes each of the 19 functions at 11 real
points, with its argument written three ways that land on a cut: conj(x),
cos(x) and i * x. It compares both compilers with evaluation, and adds
three logarithms to complex bases. 9 of its 22 cases fail on master. A
pole is left out, since there the infinity has a NaN part, which is not
what this is about. So is an exponent with an odd denominator, where
evaluation takes the real root, which a double exponent cannot show.

Fixes #2236. Fixes #2239.

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

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.70%. Comparing base (b8a6a6f) to head (c64e0a0).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2240      +/-   ##
==========================================
+ Coverage   86.68%   86.70%   +0.02%     
==========================================
  Files         310      310              
  Lines       67766    67773       +7     
  Branches    19660    19660              
==========================================
+ Hits        58744    58764      +20     
+ Misses       4909     4896      -13     
  Partials     4113     4113              
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.25% <100.00%> (+0.02%) ⬆️
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 Δ
...gouriMath/Functions/Compilation/ComplexBranches.cs 100.00% <100.00%> (ø)
...ath/Functions/Compilation/IntoFE/FastExpression.cs 96.77% <100.00%> (+0.01%) ⬆️
...h/Functions/Compilation/IntoLinq/MathAllMethods.cs 73.97% <100.00%> (+0.25%) ⬆️
.../AngouriMath/Functions/Compilation/RealProducts.cs 100.00% <100.00%> (ø)

... 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.

@Rafael-SOWNet
Rafael-SOWNet merged commit 5d4a300 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 a-compiled-zero-is-unsigned branch October 30, 2026 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

1 participant