Skip to content

Commit 09dd403

Browse files
author
Release Manager
committed
gh-36156: detect the zero series when returning an exact stream By definition, an exact stream is non-zero. Therefore, we have to check before constructing one. Fixes #36154 ### 📝 Checklist - [X] The title is concise, informative, and self-explanatory. - [X] The description explains in detail what this PR is about. - [X] I have linked a relevant issue or discussion. - [X] I have created tests covering the changes. URL: #36156 Reported by: Martin Rubey Reviewer(s): Frédéric Chapoton
2 parents 78f50ec + 64c22ca commit 09dd403

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

src/sage/rings/lazy_series.py

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,22 @@ def truncate(self, d):
625625
sage: M = z + z^2 + z^3 + z^4
626626
sage: M.truncate(4)
627627
z + z^2 + z^3
628+
629+
TESTS:
630+
631+
Check that :issue:`36154` is fixed::
632+
633+
sage: L.<z> = LazyPowerSeriesRing(QQ)
634+
sage: f = L([0,1,2])
635+
sage: f.truncate(1)
636+
0
628637
"""
629638
P = self.parent()
630639
coeff_stream = self._coeff_stream
631640
v = coeff_stream._approximate_order
632641
initial_coefficients = [coeff_stream[i] for i in range(v, d)]
642+
if not any(initial_coefficients):
643+
return P.zero()
633644
return P.element_class(P, Stream_exact(initial_coefficients, order=v))
634645

635646
def shift(self, n):
@@ -1838,6 +1849,14 @@ def _acted_upon_(self, scalar, self_on_left):
18381849
sage: 1 * M is M
18391850
True
18401851
1852+
TESTS:
1853+
1854+
Check that :issue:`36154` is fixed::
1855+
1856+
sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
1857+
sage: f = L(constant=2)
1858+
sage: 2*f
1859+
0
18411860
"""
18421861
# With the current design, the coercion model does not have
18431862
# enough information to detect a priori that this method only
@@ -1872,6 +1891,8 @@ def _acted_upon_(self, scalar, self_on_left):
18721891
else:
18731892
c = scalar * coeff_stream._constant
18741893
initial_coefficients = [scalar * val for val in init_coeffs]
1894+
if not any(initial_coefficients) and not c:
1895+
return P.zero()
18751896
return P.element_class(P, Stream_exact(initial_coefficients,
18761897
order=v,
18771898
constant=c,
@@ -2816,6 +2837,14 @@ def _mul_(self, other):
28162837
28172838
sage: (1+z) * L([1,0,1], constant=1)
28182839
1 + z + z^2 + 2*z^3 + 2*z^4 + 2*z^5 + O(z^6)
2840+
2841+
Check that :issue:`36154` is fixed::
2842+
2843+
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
2844+
sage: f = L(constant=2, valuation=0)
2845+
sage: g = L([2])
2846+
sage: f * g
2847+
0
28192848
"""
28202849
P = self.parent()
28212850
left = self._coeff_stream
@@ -2874,6 +2903,8 @@ def _mul_(self, other):
28742903
c += left._constant * ir[-1]
28752904
else:
28762905
c = left._constant # this is zero
2906+
if not any(initial_coefficients) and not c:
2907+
return P.zero()
28772908
coeff_stream = Stream_exact(initial_coefficients,
28782909
order=lv + rv,
28792910
constant=c)
@@ -2939,6 +2970,14 @@ def __pow__(self, n):
29392970
sage: (1 + z)^(1 + z)
29402971
1 + z + z^2 + 1/2*z^3 + 1/3*z^4 + 1/12*z^5 + 3/40*z^6 + O(z^7)
29412972
2973+
TESTS:
2974+
2975+
Check that :issue:`36154` is fixed::
2976+
2977+
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
2978+
sage: f = L([2])
2979+
sage: f^2
2980+
0
29422981
"""
29432982
if n == 0:
29442983
return self.parent().one()
@@ -2951,14 +2990,15 @@ def __pow__(self, n):
29512990
# return P(self.finite_part() ** ZZ(n))
29522991
P = self.parent()
29532992
ret = cs._polynomial_part(P._internal_poly_ring) ** ZZ(n)
2993+
if not ret:
2994+
return P.zero()
29542995
val = ret.valuation()
29552996
deg = ret.degree() + 1
29562997
initial_coefficients = [ret[i] for i in range(val, deg)]
29572998
return P.element_class(P, Stream_exact(initial_coefficients,
29582999
constant=cs._constant,
29593000
degree=deg,
29603001
order=val))
2961-
29623002
return super().__pow__(n)
29633003

29643004
def __invert__(self):
@@ -3806,6 +3846,17 @@ def __call__(self, g, *, check=True):
38063846
sage: g = L.undefined(valuation=0)
38073847
sage: f(g) == f.polynomial()(g)
38083848
True
3849+
3850+
TESTS:
3851+
3852+
Check that :issue:`36154` is fixed::
3853+
3854+
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
3855+
sage: f = L([0,2])
3856+
sage: g = L([2])
3857+
sage: f(g)
3858+
0
3859+
38093860
"""
38103861
# Find a good parent for the result
38113862
from sage.structure.element import get_coercion_model
@@ -3850,6 +3901,8 @@ def __call__(self, g, *, check=True):
38503901
except (ValueError, TypeError): # the result is not a Laurent polynomial
38513902
ret = None
38523903
if ret is not None and ret.parent() is R:
3904+
if not ret:
3905+
return P.zero()
38533906
val = ret.valuation()
38543907
deg = ret.degree() + 1
38553908
initial_coefficients = [ret[i] for i in range(val, deg)]
@@ -4164,6 +4217,12 @@ def derivative(self, *args):
41644217
sage: f.derivative(q)[3]
41654218
3*q^2 - 2
41664219
4220+
Check that :issue:`36154` is fixed::
4221+
4222+
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
4223+
sage: f = L([0,0,2])
4224+
sage: f.derivative()
4225+
0
41674226
"""
41684227
P = self.parent()
41694228
R = P._laurent_poly_ring
@@ -4191,6 +4250,8 @@ def derivative(self, *args):
41914250
coeffs = [prod(i-k for k in range(order)) * c
41924251
for i, c in enumerate(coeff_stream._initial_coefficients,
41934252
coeff_stream._approximate_order)]
4253+
if not any(coeffs):
4254+
return P.zero()
41944255
coeff_stream = Stream_exact(coeffs,
41954256
order=coeff_stream._approximate_order - order,
41964257
constant=coeff_stream._constant)
@@ -4993,6 +5054,14 @@ def derivative(self, *args):
49935054
+ (6*q^5*x^6+(-30*q^4)*x^5*y+60*q^3*x^4*y^2+(-60*q^2)*x^3*y^3+30*q*x^2*y^4+(-6)*x*y^5)
49945055
+ O(x,y)^7
49955056
5057+
TESTS:
5058+
5059+
Check that :issue:`36154` is fixed::
5060+
5061+
sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
5062+
sage: f = L([0,0,2])
5063+
sage: f.derivative()
5064+
0
49965065
"""
49975066
P = self.parent()
49985067
R = P._laurent_poly_ring
@@ -5038,6 +5107,8 @@ def derivative(self, *args):
50385107
coeffs = [prod(i-k for k in range(order)) * c
50395108
for i, c in enumerate(coeff_stream._initial_coefficients,
50405109
coeff_stream._approximate_order)]
5110+
if not any(coeffs):
5111+
return P.zero()
50415112
coeff_stream = Stream_exact(coeffs,
50425113
order=coeff_stream._approximate_order - order,
50435114
constant=coeff_stream._constant)

0 commit comments

Comments
 (0)