Skip to content

Add SetPrecision and SetAccuracy, as in WMA - #2057

Merged
tombouctou merged 3 commits into
masterfrom
set-precision
Oct 19, 2026
Merged

tombouctou merged 3 commits into
masterfrom
set-precision

Conversation

@tombouctou

Copy link
Copy Markdown
Collaborator

Part of step 6 of the outline in #2047. On top of the hyperbolic PR, #2056 (and the PRs below it): SetPrecision evaluates after setting the numbers, so SetPrecision[Sin[2], 20] needs Sin's rule.

SetPrecision and SetAccuracy did not exist; they came back unevaluated. They now work as in WMA 15:

Input WMA 15 and this PR
SetPrecision[1/3, 20] 0.33333333333333333333
SetPrecision[0.1, 20] 0.10000000000000000555: an inexact number keeps its binary value
SetPrecision[f[Pi, x], 20] f[3.1415926535897932385, x]: numeric constants are evaluated
SetPrecision[0.1, Infinity] 3602879701896397 / 36028797018963968
SetPrecision[1.520, MachinePrecision]` 1.5
Precision[SetPrecision[Sin[2], 20]] 20.0384: the numbers are set, then the expression is evaluated
Precision[SetPrecision[Sqrt[2], 20]] 20.301: an exact exponent stays exact
SetPrecision[0., 20] 0: a machine or arbitrary-precision zero becomes an exact 0
Precision /@ {Re[#], Im[#]} &[SetPrecision[1.5 + 2.5 I, 20.3]] {20.1619, 20.3837}: both parts get the same accuracy, so that the number has precision 20.3
Precision[SetAccuracy[150.5, 20]] 22.1775
Accuracy[SetAccuracy[0.001, 2]] 2.: no digit left, so a zero
SetPrecision[1.5, a] SetPrecision::precbd
SetPrecision[1.5, -1] SetPrecision::precsm, then $MinPrecision is used
SetAccuracy[1.5, a] SetAccuracy::accbd

Changes

  • SetPrecision and SetAccuracy in mathics/builtin/atomic/numbers.py, next to Precision and Accuracy. The work is in a new module, mathics/eval/numbers/precision.py.
  • Complex: the object cache was keyed on the parts' values and whole-bit precision. Since PrecisionReal: keep a real-valued precision, as WMA does (#2047) #2050, two complex numbers that differ only in a real-valued precision were the same object: SetAccuracy[1.5 + 2.5 I, 20] returned the result of SetPrecision[1.5 + 2.5 I, 20.3] evaluated just before it. The key now has the parts' precisions, as PrecisionReal's key does.
  • number._get_float_inf becomes get_float_inf, used by SetPrecision for $MinPrecision and $MaxPrecision.

Tests

test_set_precision, test_set_accuracy and test_set_precision_messages in test/builtin/atomic/test_numbers.py, with WMA 15 values, and doctests. Full run on kimmy: doctests all pass. The pytest failures are the ones that depend on the order the tests run in; the failing files that touch numbers pass on their own.

🤖 Generated with Claude Code

Comment thread mathics/eval/numbers/precision.py Outdated
# exact value), or None for MachinePrecision.
Target = Optional[float]

LOG10_2 = math.log10(2)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small nit: for constants like this, we've been using

from typing import Final
LOG10_2: Final[float] = math.log10(2)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in a88806c: LOG10_2: Final[float] = math.log10(2). I did the same for the constants #2060 adds to number.py (MIN_STORED_BITS, EXTENDED_DIGITS), which match the Final ones already there.

tombouctou and others added 2 commits October 20, 2026 02:03
Part of step 6 of #2047 (MATH-227), on top of the hyperbolic PR.

- SetPrecision[expr, p] sets every number in expr to precision p, and
  evaluates numeric constants such as Pi to it. An inexact number keeps
  its binary value: SetPrecision[0.1, 20] is 0.10000000000000000555. As
  in WMA, an exact exponent stays exact (SetPrecision[Sqrt[2], 20] has
  precision 20.301), and a machine or arbitrary-precision zero becomes 0.
  p can be MachinePrecision, or Infinity for the exact binary values.
- SetAccuracy[expr, a] does the same with accuracy a; a number with no
  digit left becomes a zero of accuracy a.
- Complex numbers: both parts get the same accuracy, so that the number
  has precision (or accuracy) p, as in WMA.
- Messages SetPrecision::precbd, ::precsm, ::preclg and
  SetAccuracy::accbd, as in WMA.
- Complex: the object cache was keyed on the parts' values and whole-bit
  precision, so two numbers differing only in a real-valued precision
  (#2050) were the same object. The key now has the parts' precisions.
- number._get_float_inf becomes get_float_inf, for SetPrecision.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tombouctou
tombouctou force-pushed the hyperbolic-real-valued-precision branch from 77e79f6 to 03d2771 Compare October 19, 2026 22:04
@rocky

rocky commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

LGTM - if you want to address the nit, that's up to you. Merge when you feel ready.

As asked in review, as other module constants are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tombouctou added a commit that referenced this pull request Oct 19, 2026
As other module constants are (review on #2057).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from hyperbolic-real-valued-precision to master October 19, 2026 22:33
@tombouctou
tombouctou merged commit 759612b into master Oct 19, 2026
9 checks passed
@tombouctou
tombouctou deleted the set-precision branch October 19, 2026 22:34
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.

2 participants