Skip to content

Read a computed value as a rational only within half the working digits - #2066

Merged
Rafael-SOWNet merged 4 commits into
masterfrom
a-computed-value-is-a-rational-within-half-the-digits
Oct 22, 2026
Merged

Rafael-SOWNet merged 4 commits into
masterfrom
a-computed-value-is-a-rational-within-half-the-digits

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Part of #1944.

  • The defect. Real.Create made a computed value the integer it was near within half the working digits, but made it the small rational it was near within a fixed 1e-16, whatever the precision.
    • At two thousand digits, ln(e^a + sqrt(2) e^(a/2) + 1) was exactly a, where it is a + 1.2e-67.
    • The derivative of a right antiderivative of 1/sqrt(a + i a sinh(c + d x)) at x = 227283/1250 is built on the difference of two such logarithms. So at two thousand digits it lost its imaginary part, and the corpus harness read Rubi 6.1.5 row 94 as wrong.
  • The change. The continued fraction now stops within half the working digits, as the integer test already did.
  • Machine numbers. A number from a float, a double or a decimal carries that type's digits, not the working precision's, so it keeps the 1e-16. (Entity)(1m / 3) is still 1/3, and the LaTeX tests that write a cube root as x^(1m/3) still print one.
  • Unchanged. The public FindRational keeps its tolerance too.
  • What this does not fix. The derivative is still wrong at 300 digits and NaN at 50 to 200. There, values below half the working digits are zero, including products of nonzero values, such as a modulus near 1e-136. That is a change to the floor at zero across the arithmetic, and it is the next PR.

AValueKeepsTheDigitsItHasTest asserts five things:

  • the derivative at 2000 digits, against mpmath;
  • two values near 1/3 that are not 1/3;
  • machine numbers rounded as before;
  • residuals of exact arithmetic still exact;
  • 1/3 + 1e-60 still 1/3.

Its four new-behaviour cases fail on master. Two existing tests change, and both changes are deliberate:

  • HighPrecisionFunctionsTest passes the tolerance to the exact search it compares the cheap check against.
  • AModulusIsMadeUnderTheDowncastingInForce pinned |75 + 316.22776601683796i| as 325 with the downcasting on, which was the 1e-16 snap. It is 325 + 2.6e-17, and a modulus that is 325 to the working digits is 325.

Results:

  • Unit suite: passes (16,716).
  • Corpus: the full Rubi corpus, run against the 2.6.0 run on the same harness (c614b2c8), is 48,305 of 48,305, with no row moved and no answer's allocation grown.
  • Build: the library builds for netstandard2.0.
  • BREAKING-CHANGES: the entry gives the values on 2.6.0 and now.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

Rafael-SOWNet and others added 2 commits October 22, 2026 14:40
Real.Create made a value the integer it was near within half the working
digits, and the small rational it was near within a fixed 1e-16, whatever
the precision. At two thousand digits ln(e^a + sqrt(2) e^(a/2) + 1) was
exactly a, where it is a + 1.2e-67, so the derivative of a right
antiderivative of 1/sqrt(a + i a sinh(c + d x)) at x = 227283/1250, built
on the difference of two such logarithms, lost its imaginary part, and the
corpus harness read the row as wrong. The continued fraction now stops
within half the working digits, as the integer test does.

A number from a float, a double or a decimal carries that type's digits,
not the working precision's, and keeps the 1e-16: (Entity)(1m / 3) is
still 1/3, and the LaTeX tests writing a cube root as x^(1m/3) still print
one. The public FindRational keeps its tolerance too.

The derivative is still wrong at 300 digits and NaN at 50 to 200: values
below half the working digits are zero, products of nonzero values among
them, and those are the next change.

Part of #1944.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
…-a-rational-within-half-the-digits

# Conflicts:
#	BREAKING-CHANGES.md
Rafael-SOWNet and others added 2 commits October 22, 2026 15:50
Passed as an argument, the half-digit tolerance was made on every Real.Create,
where it had been made only past the check that almost every value stops at:
EvalPolynomialFresh allocated 5.0% more and the kernel gate failed. The rational
search now takes the integer test's tolerance, already made there.

Part of #1944.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
…-a-rational-within-half-the-digits

# Conflicts:
#	BREAKING-CHANGES.md
@Rafael-SOWNet

Copy link
Copy Markdown
Member Author

The kernel gate failed on allocation: EvalPolynomialFresh +5.0% and EvalPolynomialFresh15Digits +3.6%. The tolerance was passed into Real.Create as an argument, so it was built on every call. Before, it was built only past the cheap check that almost every value stops at.

It is now made where the rational search runs, from the integer test's tolerance (0362dd76). Measured locally on that workload, in bytes per operation:

EvalPolynomialFresh EvalPolynomialFresh15Digits
master 12,743 12,077
before the fix 13,326 12,509
after the fix 12,724 12,077

Master is merged in for #2062's BREAKING-CHANGES entry.

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

@Rafael-SOWNet
Rafael-SOWNet merged commit bd19bda into master Oct 22, 2026
34 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in AngouriMath Oct 22, 2026
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