Skip to content

Commit 85da6cc

Browse files
author
Release Manager
committed
gh-35307: Use StringIO to format polynomials This patch modifies the repr()/str() method of polynomials to use a StringIO buffer instead of `s += ...` to build the result string. It is known that repeatedly calling `+=` has quadratic complexity for large Python strings. Currently calling `str()` on a high degree polynomial takes a very long amount of time and it may happen accidentally (a script was stuck during 2 hours trying to format a degree 300000 polynomial for an exception message). ``` sage: p = random_prime(2**96) sage: K = GF(p**24, 'a') sage: pol = K["x"].random_element(30000) # Before patch sage: %time _ = str(pol) CPU times: user 2min 22s, sys: 1min 43s, total: 4min 5s Wall time: 4min 5s # After patch sage: %time _ = str(pol) CPU times: user 692 ms, sys: 21 ms, total: 713 ms Wall time: 713 ms ``` ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [x] I have made sure that the title is self-explanatory and the description concisely explains the PR. - [ ] I have linked an issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation accordingly. ### ⌛ Dependencies None. URL: #35307 Reported by: Rémy Oudompheng Reviewer(s): Lorenz Panny
2 parents ea678b9 + 5da2277 commit 85da6cc

File tree

1 file changed

+7
-3
lines changed

1 file changed

+7
-3
lines changed

src/sage/rings/polynomial/polynomial_element.pyx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ from cpython.number cimport PyNumber_TrueDivide, PyNumber_Check
6565
import operator
6666
import copy
6767
import re
68+
from io import StringIO
6869

6970
from sage.cpython.wrapperdescr cimport wrapperdescr_fastcall
7071
import sage.rings.rational
@@ -2641,7 +2642,8 @@ cdef class Polynomial(CommutativePolynomial):
26412642
# want their coefficient printed with its O() term
26422643
if self._is_gen and not isinstance(self._parent._base, pAdicGeneric):
26432644
return name
2644-
s = " "
2645+
sbuf = StringIO()
2646+
sbuf.write(" ")
26452647
m = self.degree() + 1
26462648
atomic_repr = self._parent.base_ring()._repr_option('element_is_atomic')
26472649
coeffs = self.list(copy=False)
@@ -2657,7 +2659,7 @@ cdef class Polynomial(CommutativePolynomial):
26572659
is_nonzero = True
26582660
if is_nonzero:
26592661
if n != m-1:
2660-
s += " + "
2662+
sbuf.write(" + ")
26612663
x = y = repr(x)
26622664
if y.find("-") == 0:
26632665
y = y[1:]
@@ -2669,7 +2671,9 @@ cdef class Polynomial(CommutativePolynomial):
26692671
var = "*%s"%name
26702672
else:
26712673
var = ""
2672-
s += "%s%s"%(x,var)
2674+
sbuf.write(x)
2675+
sbuf.write(var)
2676+
s = sbuf.getvalue()
26732677
s = s.replace(" + -", " - ")
26742678
s = re.sub(r' 1(\.0+)?\*',' ', s)
26752679
s = re.sub(r' -1(\.0+)?\*',' -', s)

0 commit comments

Comments
 (0)