Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
sagemathgh-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 sagemath#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: sagemath#36156
Reported by: Martin Rubey
Reviewer(s): Frédéric Chapoton
  • Loading branch information
Release Manager committed Aug 31, 2023
2 parents 78f50ec + 64c22ca commit 09dd403
Showing 1 changed file with 72 additions and 1 deletion.
73 changes: 72 additions & 1 deletion src/sage/rings/lazy_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,11 +625,22 @@ def truncate(self, d):
sage: M = z + z^2 + z^3 + z^4
sage: M.truncate(4)
z + z^2 + z^3
TESTS:
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyPowerSeriesRing(QQ)
sage: f = L([0,1,2])
sage: f.truncate(1)
0
"""
P = self.parent()
coeff_stream = self._coeff_stream
v = coeff_stream._approximate_order
initial_coefficients = [coeff_stream[i] for i in range(v, d)]
if not any(initial_coefficients):
return P.zero()
return P.element_class(P, Stream_exact(initial_coefficients, order=v))

def shift(self, n):
Expand Down Expand Up @@ -1838,6 +1849,14 @@ def _acted_upon_(self, scalar, self_on_left):
sage: 1 * M is M
True
TESTS:
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
sage: f = L(constant=2)
sage: 2*f
0
"""
# With the current design, the coercion model does not have
# enough information to detect a priori that this method only
Expand Down Expand Up @@ -1872,6 +1891,8 @@ def _acted_upon_(self, scalar, self_on_left):
else:
c = scalar * coeff_stream._constant
initial_coefficients = [scalar * val for val in init_coeffs]
if not any(initial_coefficients) and not c:
return P.zero()
return P.element_class(P, Stream_exact(initial_coefficients,
order=v,
constant=c,
Expand Down Expand Up @@ -2816,6 +2837,14 @@ def _mul_(self, other):
sage: (1+z) * L([1,0,1], constant=1)
1 + z + z^2 + 2*z^3 + 2*z^4 + 2*z^5 + O(z^6)
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
sage: f = L(constant=2, valuation=0)
sage: g = L([2])
sage: f * g
0
"""
P = self.parent()
left = self._coeff_stream
Expand Down Expand Up @@ -2874,6 +2903,8 @@ def _mul_(self, other):
c += left._constant * ir[-1]
else:
c = left._constant # this is zero
if not any(initial_coefficients) and not c:
return P.zero()
coeff_stream = Stream_exact(initial_coefficients,
order=lv + rv,
constant=c)
Expand Down Expand Up @@ -2939,6 +2970,14 @@ def __pow__(self, n):
sage: (1 + z)^(1 + z)
1 + z + z^2 + 1/2*z^3 + 1/3*z^4 + 1/12*z^5 + 3/40*z^6 + O(z^7)
TESTS:
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
sage: f = L([2])
sage: f^2
0
"""
if n == 0:
return self.parent().one()
Expand All @@ -2951,14 +2990,15 @@ def __pow__(self, n):
# return P(self.finite_part() ** ZZ(n))
P = self.parent()
ret = cs._polynomial_part(P._internal_poly_ring) ** ZZ(n)
if not ret:
return P.zero()
val = ret.valuation()
deg = ret.degree() + 1
initial_coefficients = [ret[i] for i in range(val, deg)]
return P.element_class(P, Stream_exact(initial_coefficients,
constant=cs._constant,
degree=deg,
order=val))

return super().__pow__(n)

def __invert__(self):
Expand Down Expand Up @@ -3806,6 +3846,17 @@ def __call__(self, g, *, check=True):
sage: g = L.undefined(valuation=0)
sage: f(g) == f.polynomial()(g)
True
TESTS:
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
sage: f = L([0,2])
sage: g = L([2])
sage: f(g)
0
"""
# Find a good parent for the result
from sage.structure.element import get_coercion_model
Expand Down Expand Up @@ -3850,6 +3901,8 @@ def __call__(self, g, *, check=True):
except (ValueError, TypeError): # the result is not a Laurent polynomial
ret = None
if ret is not None and ret.parent() is R:
if not ret:
return P.zero()
val = ret.valuation()
deg = ret.degree() + 1
initial_coefficients = [ret[i] for i in range(val, deg)]
Expand Down Expand Up @@ -4164,6 +4217,12 @@ def derivative(self, *args):
sage: f.derivative(q)[3]
3*q^2 - 2
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyLaurentSeriesRing(Zmod(4))
sage: f = L([0,0,2])
sage: f.derivative()
0
"""
P = self.parent()
R = P._laurent_poly_ring
Expand Down Expand Up @@ -4191,6 +4250,8 @@ def derivative(self, *args):
coeffs = [prod(i-k for k in range(order)) * c
for i, c in enumerate(coeff_stream._initial_coefficients,
coeff_stream._approximate_order)]
if not any(coeffs):
return P.zero()
coeff_stream = Stream_exact(coeffs,
order=coeff_stream._approximate_order - order,
constant=coeff_stream._constant)
Expand Down Expand Up @@ -4993,6 +5054,14 @@ def derivative(self, *args):
+ (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)
+ O(x,y)^7
TESTS:
Check that :issue:`36154` is fixed::
sage: L.<z> = LazyPowerSeriesRing(Zmod(4))
sage: f = L([0,0,2])
sage: f.derivative()
0
"""
P = self.parent()
R = P._laurent_poly_ring
Expand Down Expand Up @@ -5038,6 +5107,8 @@ def derivative(self, *args):
coeffs = [prod(i-k for k in range(order)) * c
for i, c in enumerate(coeff_stream._initial_coefficients,
coeff_stream._approximate_order)]
if not any(coeffs):
return P.zero()
coeff_stream = Stream_exact(coeffs,
order=coeff_stream._approximate_order - order,
constant=coeff_stream._constant)
Expand Down

0 comments on commit 09dd403

Please sign in to comment.