Skip to content

Power, Sqrt: precision from the condition number, as in WMA - #2052

Merged
tombouctou merged 3 commits into
masterfrom
power-real-valued-precision
Oct 19, 2026
Merged

tombouctou merged 3 commits into
masterfrom
power-real-valued-precision

Conversation

@tombouctou

@tombouctou tombouctou commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Part of step 6 of the outline in #2047, after #2051 (merged). The PRs for Log (#2053), the trigonometric and hyperbolic functions (#2054–#2056), SetPrecision (#2057) and low-precision values (#2060) are stacked on this one.

Power and Sqrt get their precision from the condition number, as WMA does. The relative error of b^e is Abs[e] times that of b, plus Abs[e Log[b]] times that of e.

Input master / #2051 this PR WMA 15
Precision[Sqrt[1.5`20]] 20. 20.301 20.301
Precision[1.5`20^3] 20. 19.5229 19.5229
Precision[1.5`20^1000] 20. 17. 17.
Precision[1.5`20^(10^-5)] 20. 25. 25.
Precision[2^1.5`20] 20. 19.9831 19.9831
Precision[10^100.`20] 20. 17.6378 17.6378
Precision[1.5`20^2.5`20] 20. 19.4542 19.4542
Precision[Exp[1.5`20]] 20. 19.8239 19.8239

Changes

  • MPMathFunction.condition_numbers (mathics/core/builtin.py), new and optional. Given the arguments and the value as mpmath numbers, it returns the factor Abs[x D[f, x] / f] for each argument. The follow-up PRs give it to Log, the trigonometric and the hyperbolic functions; each of those PRs only adds the formulas.
  • eval_mpmath_function_by_condition (mathics/eval/numeric.py) uses it when the arguments are exact reals or nonzero PrecisionReals and the value is a nonzero real. The relative errors add up, as in Times from PrecisionReal: keep a real-valued precision, as WMA does (#2047) #2050. When the result has more digits than the arguments (Sqrt, x^(10^-5)), the value is computed again with enough bits. Everything else (complex results, machine numbers, zeros) takes the path it took before.
  • Power gives (Abs[e], Abs[e Log[b]]). The factors are typed as mpmath.mpf, not floats: a tiny one would underflow to 0.. Sqrt[x] is x^(1/2), and Exp[x] is E^x.
  • eval_N (the internal N) now evaluates as the N builtin does since N[expr, p]: precision exactly p, with extra digits as needed, as in WMA #2051, without the message. Inside N, the 1/2 of Sqrt[2] becomes 0.5 with the requested digits. With this PR its error counts, so eval_N[Sqrt[2], $MachinePrecision] came out with precision 15.07. N gives 15.9546, as WMA does. Two cases in test_evaluators.py now expect the WMA value of N[Sqrt[2], $MachinePrecision] and N[Pi, $MachinePrecision].

Not changed: WMA counts an error for Pi in Pi^1.5`20 (19.4925), but not for E in E^1.5`20. Since #2050, exact constants add no error, so this PR gives 19.7652.

Tests

  • test_power_real_valued_precision in test/builtin/atomic/test_numbers.py, with WMA 15 values, and the digits of two results.

Full run on kimmy (pytest -n 4 and docpipeline.py):

  • Doctests: all pass.
  • pytest: the failures are the ones that depend on the order the tests run in (contexts, packages, patterns, rules, …). Their number changes from run to run. The failing files that touch numbers (test_gamma.py) pass on their own.

Benchmark

kimmy, best of 7, this PR next to #2051, both runs at the same time:

#2051 this PR
Total[Table[N[1/k, 50], {k, 2000}]] 2687 ms 2564 ms
Times @@ Table[N[1 + 1/k, 50], {k, 2000}] 3187 ms 3049 ms
Do[x = N[k, 50] + Pi, {k, 2000}] 5492 ms 5201 ms
Total[Table[1./k, {k, 2000}]] (machine reals) 1897 ms 1820 ms
Do[Sqrt[N[k, 50]], {k, 2000}] 5412 ms 5188 ms
Do[N[k, 50]^3, {k, 2000}] 4229 ms 4038 ms
Do[2^N[k, 50], {k, 2000}] 4263 ms 4034 ms

No slowdown.

🤖 Generated with Claude Code

tombouctou and others added 3 commits October 20, 2026 01:18
Part of step 6 of #2047 (MATH-227), on top of #2051.

MPMathFunction gets an optional condition_numbers: for each argument,
the factor Abs[x D[f, x] / f] by which its relative error is multiplied
in the result. When the arguments are exact reals or nonzero
PrecisionReals and the value is a nonzero real, these errors add up, as
in WMA. Power gives Abs[e] for the base and Abs[e Log[b]] for the
exponent; Sqrt[x] is x^(1/2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
eval_N is documented as the same as N[expr, p], but it kept whatever
precision the computation gave. With Sqrt adding Log10[2], and the 1/2
in Sqrt[2] made inexact by N, eval_N[Sqrt[2], $MachinePrecision] came
out with precision 15.07, while N gives 15.9546, as WMA does. It now
uses the same evaluation as N, without the message.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
As asked in review: the arguments, the value and the factors are mpmath
numbers. They stay so, rather than floats: a tiny factor such as that of
Tanh[10.`20^6] would underflow to 0. as a float.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tombouctou
tombouctou force-pushed the power-real-valued-precision branch from 7a6e2b4 to 5ff0c56 Compare October 19, 2026 21:18
@tombouctou
tombouctou merged commit 83032f7 into master Oct 19, 2026
15 checks passed
@tombouctou
tombouctou deleted the power-real-valued-precision branch October 19, 2026 22:18
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