Skip to content

A zero imaginary part is on the real axis, whatever its sign - #1433

Merged
Rafael-SOWNet merged 2 commits into
masterfrom
signed-zero-branch
Sep 21, 2026
Merged

Rafael-SOWNet merged 2 commits into
masterfrom
signed-zero-branch

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Found while checking a Rubi 7.4.2 answer: e^acoth(a x) sqrt(c - c/(a x))/x^2 read wrong in the integration probe on the region where sqrt(c - c/(a x)) is imaginary, and finite differences of the same antiderivative under the default settings matched the integrand exactly. The probe, like intbench, evaluates with DowncastingEnabled off ("decimals stay decimals"), and there the evaluation was wrong.

The cause. A decimal's negative zero — 0E-100 * -0.43 is -0E-102 — is an artefact of the exponent arithmetic, not a limit from below (EDecimal.Sign is 0 for it). Arctan2 read -pi off its sign the way Math.Atan2 does; with the downcasting off Complex.Create keeps -1.54 - 0i a Complex, so a power went through the polar form a hair below the negative axis: (2*1.44*(1/sqrt(-5.286))^2-1)^(-1/2) was +0.80 i with the setting off and -0.80 i with it on. A setting decided a branch — #1376's point, one layer down.

The fix. A number on the negative axis has argument pi for either zero (the three Arctan2 arms); the square root reads its sign from a strictly negative imaginary part (im.Sign < 0); and a complex base or power whose imaginary part is exactly zero takes the real paths of Pow, where the half-power arithmetic is exact rather than a cosine of pi/2 at a hundred digits. Complex.Create is unchanged, so the type semantics of the setting (NumericDowncastingTest) are as they were. Nothing changes with the downcasting on.

SignedZeroBranchTest: four expressions evaluate to the same value with the setting on and off (to 1e-40), and -4 - 0i has sqrt, (·)^(1/2) and ln on the principal branch. Full suite 12012 passed, 0 failed; benchmark gate PASSED (SimplifyHard 171,750,488 B, +0.1% on the recorded baseline). BREAKING-CHANGES.md rows measured on a v2.5.0 build (the Was values are the setting-off ones; 2.5.0 gave a real 5.55 for the first).

Part of #1378.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Rafael-SOWNet and others added 2 commits September 21, 2026 01:51
A decimal's negative zero -- 0E-100 * -0.43 is -0E-102 -- is an artefact of the exponent
arithmetic and not a limit from below, but the phase read -pi off its sign the way
Math.Atan2 does. With the downcasting off Complex.Create keeps -1.54 - 0i a Complex, and
a power went through the polar form a hair below the negative axis: (-1.54)^(-1/2) was
+0.80 i with the setting off and -0.80 i with it on. The setting decided a branch, and the
numerical checks in the harnesses, which turn the downcasting off, called a right
antiderivative wrong on the strength of it (Rubi 7.4.2, e^acoth(a x) sqrt(c - c/(a x))/x^2).

Now a number on the negative axis has argument pi for either zero (EDecimal.Sign is 0 for
both), the square root reads its sign from a strictly negative imaginary part, and a
complex base or power with an exactly zero imaginary part takes the real paths of Pow,
where the half-power arithmetic is exact rather than a cosine of pi/2 at a hundred
digits. Nothing changes with the downcasting on.

#1378

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
@Rafael-SOWNet
Rafael-SOWNet merged commit 4961025 into master Sep 21, 2026
31 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the signed-zero-branch branch September 21, 2026 02:28
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.

1 participant