Skip to content

Commit 3fe50d2

Browse files
author
Release Manager
committed
sagemathgh-40178: Make preparser can handle large(4301+ digits) integers <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes sagemath#12345". --> I'm pretty sure sage wants to use all kinds of numbers without losing precision, or errors, since I can see `sys.set_int_max_str_digits(0)` in all.py. However, even with the limit set to 0 (unlimited) in all.py which is called during import, it still cannot handle 4301+ digits integers, because Python refuses to run if there's 4301+ digit number in the first place. For example, the following sage code has the following error (the 11...11 is actually 5000 digits of 1): **long.sage** ``` a = 11...11 ``` ``` sage long.sage File "/home/soon_haari/mysage/long.sage.py", line 6 _sage_const_11...11 SyntaxError: Exceeds the limit (4300 digits) for integer string conversion: value has 5000 digits; use sys.set_int_max_str_digits() to increase the limit - Consider hexadecimal for huge integer literals to avoid decimal conversion limits. ``` In more details, `11...11` parses to `Integer(11...11)` where 11...11 in Integer is supposed to be `<class 'int'>` in Python. I suggest it parses to `Integer('11...11')` instead. Funnily enough, real/complex numbers like `1.1` or `1j` or even `1.1j` have no problem due to long digits, because it parses to `RealNumber('1.1')`, `ComplexNumber(0, '1')`, `ComplexNumber(0, '1.1')` which use string as arguments already. I suggest the same fix. This fixes sagemath#40179. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#40178 Reported by: Minsun Kim Reviewer(s): Minsun Kim, Travis Scrimshaw, user202729, Vincent Macri
2 parents add7bb4 + 266a113 commit 3fe50d2

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

src/sage/repl/preparse.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,8 +1124,9 @@ def preparse_numeric_literals(code, extract=False, quotes="'"):
11241124
name-construction pairs
11251125
11261126
- ``quotes`` -- string (default: ``"'"``); used to surround string
1127-
arguments to RealNumber and ComplexNumber. If ``None``, will rebuild
1128-
the string using a list of its Unicode code-points.
1127+
arguments to RealNumber and ComplexNumber, and Integer when the
1128+
number is longer than 4300 digits. If ``None``, will rebuild the
1129+
string using a list of its Unicode code-points.
11291130
11301131
OUTPUT:
11311132
@@ -1189,6 +1190,15 @@ def preparse_numeric_literals(code, extract=False, quotes="'"):
11891190
sage: preparse_numeric_literals('000042')
11901191
'Integer(42)'
11911192
1193+
Check that :issue:`40179` is fixed::
1194+
1195+
sage: preparse_numeric_literals("1" * 4300) == f"Integer({'1' * 4300})"
1196+
True
1197+
sage: preparse_numeric_literals("1" * 4301) == f"Integer('{'1' * 4301}')"
1198+
True
1199+
sage: preparse_numeric_literals("1" * 4301, quotes=None) == f'Integer(str().join(map(chr, {[49] * 4301})))'
1200+
True
1201+
11921202
Test underscores as digit separators (PEP 515,
11931203
https://www.python.org/dev/peps/pep-0515/)::
11941204
@@ -1324,7 +1334,13 @@ def preparse_numeric_literals(code, extract=False, quotes="'"):
13241334
# Python 3 does not allow leading zeroes. Sage does, so just strip them out.
13251335
# The number is still interpreted as decimal, not octal!
13261336
num = re.sub(r'^0+', '', num)
1327-
num_make = "Integer(%s)" % num
1337+
if len(num) <= 4300:
1338+
num_make = "Integer(%s)" % num
1339+
elif quotes:
1340+
num_make = "Integer(%s%s%s)" % (quotes, num, quotes)
1341+
else:
1342+
code_points = list(map(ord, list(num)))
1343+
num_make = "Integer(str().join(map(chr, %s)))" % code_points
13281344

13291345
literals[num_name] = num_make
13301346

0 commit comments

Comments
 (0)