From 2532b9e9519a84fc2727f3c899ef6e0a08b658de Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 11 Aug 2021 22:44:29 +1000 Subject: [PATCH 1/7] Make sure to test for 0 in the base ring for CS_map_coefficients. --- src/sage/data_structures/coefficient_stream.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sage/data_structures/coefficient_stream.py b/src/sage/data_structures/coefficient_stream.py index 6be22bd7561..2a1b154846a 100644 --- a/src/sage/data_structures/coefficient_stream.py +++ b/src/sage/data_structures/coefficient_stream.py @@ -1584,8 +1584,14 @@ def get_coefficient(self, n): sage: g = CoefficientStream_map_coefficients(f, lambda n: n.degree() + 1, R) sage: [g.get_coefficient(i) for i in range(-1, 3)] [1, 0, 1, 1] + + sage: f = CoefficientStream_coefficient_function(lambda n: n, ZZ, True, 0) + sage: g = CoefficientStream_map_coefficients(f, lambda n: 5, GF(3)) + sage: [g.get_coefficient(i) for i in range(10)] + [0, 5, 5, 0, 5, 5, 0, 5, 5, 0] """ - c = self._series[n] + c = self._ring(self._series[n]) if c: - return self._function(self._ring(c)) + return self._function(c) return c + From 906946f87cce50e30d5759d5531e8a11424b91dc Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Aug 2021 00:46:51 +1000 Subject: [PATCH 2/7] Using _acted_upon_ instead of _r/lmul_. Optimize -1 * f. Fix bug in _neg_. --- src/sage/rings/lazy_laurent_series.py | 143 ++++++++++----------- src/sage/rings/lazy_laurent_series_ring.py | 2 +- 2 files changed, 68 insertions(+), 77 deletions(-) diff --git a/src/sage/rings/lazy_laurent_series.py b/src/sage/rings/lazy_laurent_series.py index 062c8d9b8ea..5c6843957f1 100644 --- a/src/sage/rings/lazy_laurent_series.py +++ b/src/sage/rings/lazy_laurent_series.py @@ -715,14 +715,14 @@ def _sub_(self, other): return P.zero() return P.element_class(P, CoefficientStream_sub(self._coeff_stream, other._coeff_stream)) - def _lmul_(self, scalar): + def _acted_upon_(self, scalar, self_on_left): r""" - Scalar multiplication for module elements with the module - element on the left and the scalar on the right. + Scalar multiplication for ``self`` by ``scalar``. INPUT: - ``scalar`` -- an element of the base ring + - ``self_on_left`` -- boolean; if ``True``, compute ``self * scalar`` EXAMPLES: @@ -733,10 +733,21 @@ def _lmul_(self, scalar): sage: O = M * 2 sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] - sage: M * 1== M + sage: type(O._coeff_stream) + + sage: M * 1 is M + True + sage: M * 0 == 0 + True + sage: O = 2 * M + sage: type(O._coeff_stream) + + sage: O[0:10] + [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] + sage: 1 * M is M + True + sage: 0 * M == 0 True - sage: M * 0 - 0 Sparse series can be multiplied with a scalar:: @@ -745,101 +756,76 @@ def _lmul_(self, scalar): sage: O = M * 2 sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] - sage: M * 1== M + sage: type(O._coeff_stream) + + sage: M * 1 is M True - sage: M * 0 - 0 - - Series which are known to be exact can be multiplied with a scalar:: - - sage: N = L([0, 1]) - sage: O = N * -1 - sage: O[0:10] - [0, -1, 0, 0, 0, 0, 0, 0, 0, 0] - sage: N * 1 == N + sage: M * 0 == 0 True - sage: N * 0 - 0 - """ - P = self.parent() - if not scalar: - return P.zero() - if scalar == 1: - return self - - if isinstance(self._coeff_stream, CoefficientStream_exact): - c = self._coeff_stream._constant * scalar - v = self._coeff_stream.order() - init_coeffs = self._coeff_stream._initial_coefficients - initial_coefficients = [val * scalar for val in init_coeffs] - return P.element_class(P, CoefficientStream_exact(initial_coefficients, P._sparse, - order=v, constant=c, - degree=self._coeff_stream._degree)) - return P.element_class(P, CoefficientStream_lmul(self._coeff_stream, scalar)) - - def _rmul_(self, scalar): - r""" - Scalar multiplication for module elements with the module - element on the right and the scalar on the left. - - INPUT: - - - ``scalar`` -- an element of the base ring - - EXAMPLES: - - Dense series can be multiplied with a scalar:: - - sage: L. = LazyLaurentSeriesRing(ZZ, sparse=False) - sage: M = L(lambda n: 1 + n, valuation=0) sage: O = 2 * M + sage: type(O._coeff_stream) + sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] - sage: 1 * M == M + sage: 1 * M is M + True + sage: 0 * M == 0 True - sage: 0 * M - 0 - Sparse series can be multiplied with a scalar:: + Series which are known to be exact can be multiplied with a scalar + and remain exact:: - sage: L. = LazyLaurentSeriesRing(ZZ, sparse=True) - sage: M = L(lambda n: 1 + n, valuation=0) - sage: O = 2 * M + sage: N = L([0, 1], degree=5, constant=3) + sage: O = N * -1 sage: O[0:10] - [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] - sage: 1 * M == M + [0, -1, 0, 0, 0, -3, -3, -3, -3, -3] + sage: N * 1 is N + True + sage: N * 0 == 0 True - sage: 0 * M - 0 - - Series which are known to be exact can be multiplied with a scalar:: - - sage: N = L([0, 1]) sage: O = -1 * N sage: O[0:10] - [0, -1, 0, 0, 0, 0, 0, 0, 0, 0] - sage: 1 * N == N + [0, -1, 0, 0, 0, -3, -3, -3, -3, -3] + sage: 1 * N is N + True + sage: 0 * N == 0 True - sage: 0 * N - 0 """ + # With the current design, the coercion model does not have + # enough information to detect a priori that this method only + # accepts scalars; so it tries on some elements(), and we need + # to make sure to report an error. P = self.parent() + R = P.base_ring() + if isinstance(scalar, Element) and scalar.parent() is not R: + # Temporary needed by coercion (see Polynomial/FractionField tests). + if R.has_coerce_map_from(scalar.parent()): + scalar = R(scalar) + else: + return None + if not scalar: return P.zero() - if scalar == 1: + if scalar == R.one(): return self + if scalar == -R.one(): + return -self if isinstance(self._coeff_stream, CoefficientStream_exact): - c = scalar * self._coeff_stream._constant v = self._coeff_stream.order() init_coeffs = self._coeff_stream._initial_coefficients - initial_coefficients = [scalar * val for val in init_coeffs] + if self_on_left: + c = self._coeff_stream._constant * scalar + initial_coefficients = [val * scalar for val in init_coeffs] + else: + c = scalar * self._coeff_stream._constant + initial_coefficients = [scalar * val for val in init_coeffs] return P.element_class(P, CoefficientStream_exact(initial_coefficients, P._sparse, order=v, constant=c, degree=self._coeff_stream._degree)) - if P.base_ring().is_commutative(): - return P.element_class(P, CoefficientStream_lmul(self._coeff_stream, scalar)) - return P.element_class(P, CoefficientStream_rmul(self._coeff_stream, scalar)) + if self_on_left or R.is_commutative(): + return P.element_class(P, CoefficientStream_rmul(self._coeff_stream, scalar)) + return P.element_class(P, CoefficientStream_lmul(self._coeff_stream, scalar)) def _neg_(self): """ @@ -896,6 +882,10 @@ def _neg_(self): [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] sage: O == M True + + sage: N = L([0, 1], degree=5, constant=2) + sage: -N + -z - 2*z^5 - 2*z^6 - 2*z^7 + O(z^8) """ P = self.parent() coeff_stream = self._coeff_stream @@ -904,6 +894,7 @@ def _neg_(self): constant = -coeff_stream._constant coeff_stream = CoefficientStream_exact(initial_coefficients, P._sparse, constant=constant, + degree=coeff_stream._degree, order=coeff_stream.order()) return P.element_class(P, coeff_stream) # -(-f) = f diff --git a/src/sage/rings/lazy_laurent_series_ring.py b/src/sage/rings/lazy_laurent_series_ring.py index ec0f501b987..0a80bfbe1a3 100644 --- a/src/sage/rings/lazy_laurent_series_ring.py +++ b/src/sage/rings/lazy_laurent_series_ring.py @@ -394,7 +394,7 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No sage: g z^5 + 3*z^6 + 5*z^7 + 7*z^8 + 9*z^9 - z^10 - z^11 - z^12 + O(z^13) - Checking the valuation is consistant:: + Checking the valuation is consistent:: sage: L([0,0,2,3], valuation=-4) 2*z^-4 + 3*z^-3 From d0a677fa3f45f08ba4aad8aa3cbd3424b8d0a4a5 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Aug 2021 10:25:52 +1000 Subject: [PATCH 3/7] Have composition take the product type as input. --- .../data_structures/coefficient_stream.py | 29 ++++++++++++------- src/sage/rings/lazy_laurent_series.py | 26 ++++++++++------- src/sage/rings/lazy_laurent_series_ring.py | 6 +++- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/sage/data_structures/coefficient_stream.py b/src/sage/data_structures/coefficient_stream.py index 2a1b154846a..340cbb058da 100644 --- a/src/sage/data_structures/coefficient_stream.py +++ b/src/sage/data_structures/coefficient_stream.py @@ -1208,37 +1208,42 @@ class CoefficientStream_composition(CoefficientStream_binary): EXAMPLES:: - sage: from sage.data_structures.coefficient_stream import (CoefficientStream_composition, CoefficientStream_coefficient_function) + sage: from sage.data_structures.coefficient_stream import CoefficientStream_composition, CoefficientStream_coefficient_function + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_product as CS_prod + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_inverse as CS_inv sage: f = CoefficientStream_coefficient_function(lambda n: n, ZZ, True, 1) sage: g = CoefficientStream_coefficient_function(lambda n: 1, ZZ, True, 1) - sage: h = CoefficientStream_composition(f, g) + sage: h = CoefficientStream_composition(f, g, CS_prod, CS_inv) sage: [h[i] for i in range(10)] [0, 1, 3, 8, 20, 48, 112, 256, 576, 1280] - sage: u = CoefficientStream_composition(g, f) + sage: u = CoefficientStream_composition(g, f, CS_prod, CS_inv) sage: [u[i] for i in range(10)] [0, 1, 3, 8, 21, 55, 144, 377, 987, 2584] """ - def __init__(self, f, g): + def __init__(self, f, g, prod_stream, inv_stream): """ Initialize ``self``. TESTS:: - sage: from sage.data_structures.coefficient_stream import (CoefficientStream_coefficient_function, CoefficientStream_composition) + sage: from sage.data_structures.coefficient_stream import CoefficientStream_coefficient_function, CoefficientStream_composition + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_product as CS_prod + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_inverse as CS_inv sage: f = CoefficientStream_coefficient_function(lambda n: 1, ZZ, True, 1) sage: g = CoefficientStream_coefficient_function(lambda n: n^2, ZZ, True, 1) - sage: h = CoefficientStream_composition(f, g) + sage: h = CoefficientStream_composition(f, g, CS_prod, CS_inv) """ assert g._approximate_order > 0 self._fv = f._approximate_order self._gv = g._approximate_order + self._prod_stream = prod_stream if self._fv < 0: - ginv = CoefficientStream_cauchy_inverse(g) + ginv = inv_stream(g) # the constant part makes no contribution to the negative # we need this for the case so self._neg_powers[0][n] => 0 self._neg_powers = [CoefficientStream_zero(f._is_sparse), ginv] for i in range(1, -self._fv): - self._neg_powers.append(CoefficientStream_cauchy_product(self._neg_powers[-1], ginv)) + self._neg_powers.append(self._prod_stream(self._neg_powers[-1], ginv)) # Placeholder None to make this 1-based self._pos_powers = [None, g] val = self._fv * self._gv @@ -1254,10 +1259,12 @@ def get_coefficient(self, n): EXAMPLES:: - sage: from sage.data_structures.coefficient_stream import (CoefficientStream_coefficient_function, CoefficientStream_composition) + sage: from sage.data_structures.coefficient_stream import CoefficientStream_coefficient_function, CoefficientStream_composition + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_product as CS_prod + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_inverse as CS_inv sage: f = CoefficientStream_coefficient_function(lambda n: n, ZZ, True, 1) sage: g = CoefficientStream_coefficient_function(lambda n: n^2, ZZ, True, 1) - sage: h = CoefficientStream_composition(f, g) + sage: h = CoefficientStream_composition(f, g, CS_prod, CS_inv) sage: h.get_coefficient(5) 527 sage: [h.get_coefficient(i) for i in range(10)] @@ -1267,7 +1274,7 @@ def get_coefficient(self, n): return sum(self._left[i] * self._neg_powers[-i][n] for i in range(self._fv, n // self._gv + 1)) # n > 0 while len(self._pos_powers) <= n // self._gv: - self._pos_powers.append(CoefficientStream_cauchy_product(self._pos_powers[-1], self._right)) + self._pos_powers.append(self._prod_stream(self._pos_powers[-1], self._right)) ret = sum(self._left[i] * self._neg_powers[-i][n] for i in range(self._fv, 0)) if n == 0: ret += self._left[0] diff --git a/src/sage/rings/lazy_laurent_series.py b/src/sage/rings/lazy_laurent_series.py index 5c6843957f1..68470da6856 100644 --- a/src/sage/rings/lazy_laurent_series.py +++ b/src/sage/rings/lazy_laurent_series.py @@ -1448,11 +1448,8 @@ def __call__(self, g): ... ValueError: can only compose with a positive valuation series - We cannot compose if `g` has a negative valuation:: - sage: f = L(lambda n: n, 1) - sage: g = 1 + z - sage: f(g) + sage: f(1 + z) Traceback (most recent call last): ... ValueError: can only compose with a positive valuation series @@ -1460,6 +1457,10 @@ def __call__(self, g): # f = self and compute f(g) P = g.parent() + # f = 0 + if isinstance(self._coeff_stream, CoefficientStream_zero): + return self + # g = 0 case if ((not isinstance(g, LazyLaurentSeries) and not g) or (isinstance(g, LazyLaurentSeries) @@ -1472,16 +1473,14 @@ def __call__(self, g): self._coeff_stream._approximate_order = 0 return P(self[0]) - # f has finite length - if isinstance(self._coeff_stream, CoefficientStream_zero): # constant 0 - return self + # f has finite length and f != 0 if isinstance(self._coeff_stream, CoefficientStream_exact) and not self._coeff_stream._constant: # constant polynomial R = self.parent()._laurent_poly_ring poly = self._coeff_stream.polynomial_part(R) if poly.is_constant(): return self - if not isinstance(g, LazyLaurentSeries): + if not isinstance(g, LazyModuleElement): return poly(g) # g also has finite length, compose the polynomials if isinstance(g._coeff_stream, CoefficientStream_exact) and not g._coeff_stream._constant: @@ -1528,18 +1527,23 @@ def __call__(self, g): return ret # g != 0 and val(g) > 0 - if not isinstance(g, LazyLaurentSeries): + if not isinstance(g, LazyModuleElement): + # TODO: Implement case for a regular (Laurent)PowerSeries element + # as we can use the (default?) order given try: g = self.parent()(g) except (TypeError, ValueError): - raise NotImplementedError("can only compose with a lazy Laurent series") + raise NotImplementedError("can only compose with a lazy series") # Perhaps we just don't yet know if the valuation is positive if g._coeff_stream._approximate_order <= 0: if any(g._coeff_stream[i] for i in range(g._coeff_stream._approximate_order, 1)): raise ValueError("can only compose with a positive valuation series") g._coeff_stream._approximate_order = 1 - return P.element_class(P, CoefficientStream_composition(self._coeff_stream, g._coeff_stream)) + return P.element_class(P, CoefficientStream_composition(self._coeff_stream, + g._coeff_stream, P._product_stream_class, P._product_inv_stream_class)) + + compose = __call__ def _div_(self, other): r""" diff --git a/src/sage/rings/lazy_laurent_series_ring.py b/src/sage/rings/lazy_laurent_series_ring.py index 0a80bfbe1a3..8424e11a0ba 100644 --- a/src/sage/rings/lazy_laurent_series_ring.py +++ b/src/sage/rings/lazy_laurent_series_ring.py @@ -37,7 +37,9 @@ CoefficientStream_zero, CoefficientStream_coefficient_function, CoefficientStream_exact, - CoefficientStream_uninitialized + CoefficientStream_uninitialized, + CoefficientStream_cauchy_product, + CoefficientStream_cauchy_inverse ) @@ -144,6 +146,8 @@ class LazyLaurentSeriesRing(UniqueRepresentation, Parent): False """ Element = LazyLaurentSeries + _product_stream_class = CoefficientStream_cauchy_product + _product_inv_stream_class = CoefficientStream_cauchy_inverse def __init__(self, base_ring, names, sparse=True, category=None): """ From c38900b96a873b4cc13cdc74bcb22fceb16221b8 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Aug 2021 10:34:33 +1000 Subject: [PATCH 4/7] Changing to instead use an if-check for deciding product in composition. --- .../data_structures/coefficient_stream.py | 25 ++++++++----------- src/sage/rings/lazy_laurent_series.py | 7 +++++- src/sage/rings/lazy_laurent_series_ring.py | 6 +---- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/src/sage/data_structures/coefficient_stream.py b/src/sage/data_structures/coefficient_stream.py index 340cbb058da..d4a8d9eb815 100644 --- a/src/sage/data_structures/coefficient_stream.py +++ b/src/sage/data_structures/coefficient_stream.py @@ -17,11 +17,10 @@ sage: type(f._coeff_stream) - There are basic unary and binary operators available for the coefficient streams. - For example, we can add two streams together:: +There are basic unary and binary operators available for the coefficient +streams. For example, we can add two streams together:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_coefficient_function - sage: from sage.data_structures.coefficient_stream import CoefficientStream_add + sage: from sage.data_structures.coefficient_stream import * sage: f = CoefficientStream_coefficient_function(lambda n: n, QQ, True, 0) sage: [f[i] for i in range(10)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -34,21 +33,18 @@ Coefficient streams can be subtracted:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_sub sage: h = CoefficientStream_sub(f, g) sage: [h[i] for i in range(10)] [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8] Coefficient streams can be multiplied:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_product sage: h = CoefficientStream_cauchy_product(f, g) sage: [h[i] for i in range(10)] [0, 1, 3, 6, 10, 15, 21, 28, 36, 45] Coefficient streams can be divided:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_inverse sage: ginv = CoefficientStream_cauchy_inverse(g) sage: h = CoefficientStream_cauchy_product(f, ginv) sage: [h[i] for i in range(10)] @@ -56,36 +52,33 @@ Two coefficient streams can be composed (depending on whether it exists):: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_composition + sage: CS_prod = CoefficientStream_cauchy_product + sage: CS_inv = CoefficientStream_cauchy_inverse sage: g = CoefficientStream_coefficient_function(lambda n: n, QQ, True, 1) - sage: h = CoefficientStream_composition(f, g) + sage: h = CoefficientStream_composition(f, g, CS_prod, CS_inv) sage: [h[i] for i in range(10)] [0, 1, 4, 14, 46, 145, 444, 1331, 3926, 11434] We can also use the unary negation operator on a coefficient stream:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_neg sage: h = CoefficientStream_neg(f) sage: [h[i] for i in range(10)] [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] Coefficient streams can be multiplied by a scalar:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_lmul sage: h = CoefficientStream_lmul(f, 2) sage: [h[i] for i in range(10)] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] The multiplicative inverse of a series can also be obtained:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_inverse sage: h = CoefficientStream_cauchy_inverse(g) sage: [h[i] for i in range(10)] [-2, 1, 0, 0, 0, 0, 0, 0, 0, 0] Functions can also be applied to a coefficient stream:: - sage: from sage.data_structures.coefficient_stream import CoefficientStream_map_coefficients sage: h = CoefficientStream_map_coefficients(f, lambda n: n^2, QQ) sage: [h[i] for i in range(10)] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] @@ -295,10 +288,12 @@ def iterate_coefficients(self): EXAMPLES:: - sage: from sage.data_structures.coefficient_stream import (CoefficientStream_coefficient_function, CoefficientStream_composition) + sage: from sage.data_structures.coefficient_stream import CoefficientStream_coefficient_function, CoefficientStream_composition + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_product as CS_prod + sage: from sage.data_structures.coefficient_stream import CoefficientStream_cauchy_inverse as CS_inv sage: f = CoefficientStream_coefficient_function(lambda n: 1, ZZ, False, 1) sage: g = CoefficientStream_coefficient_function(lambda n: n^3, ZZ, False, 1) - sage: h = CoefficientStream_composition(f, g) + sage: h = CoefficientStream_composition(f, g, CS_prod, CS_inv) sage: n = h.iterate_coefficients() sage: [next(n) for i in range(10)] [1, 9, 44, 207, 991, 4752, 22769, 109089, 522676, 2504295] diff --git a/src/sage/rings/lazy_laurent_series.py b/src/sage/rings/lazy_laurent_series.py index 68470da6856..8664f019207 100644 --- a/src/sage/rings/lazy_laurent_series.py +++ b/src/sage/rings/lazy_laurent_series.py @@ -1540,8 +1540,13 @@ def __call__(self, g): raise ValueError("can only compose with a positive valuation series") g._coeff_stream._approximate_order = 1 + if isinstance(g, LazyCauchyProductSeries): + CS_prod = CoefficientStream_cauchy_product + CS_inv = CoefficientStream_cauchy_inverse + else: + raise NotImplementedError("undefined product coefficient stream") return P.element_class(P, CoefficientStream_composition(self._coeff_stream, - g._coeff_stream, P._product_stream_class, P._product_inv_stream_class)) + g._coeff_stream, CS_prod, CS_inv)) compose = __call__ diff --git a/src/sage/rings/lazy_laurent_series_ring.py b/src/sage/rings/lazy_laurent_series_ring.py index 8424e11a0ba..0a80bfbe1a3 100644 --- a/src/sage/rings/lazy_laurent_series_ring.py +++ b/src/sage/rings/lazy_laurent_series_ring.py @@ -37,9 +37,7 @@ CoefficientStream_zero, CoefficientStream_coefficient_function, CoefficientStream_exact, - CoefficientStream_uninitialized, - CoefficientStream_cauchy_product, - CoefficientStream_cauchy_inverse + CoefficientStream_uninitialized ) @@ -146,8 +144,6 @@ class LazyLaurentSeriesRing(UniqueRepresentation, Parent): False """ Element = LazyLaurentSeries - _product_stream_class = CoefficientStream_cauchy_product - _product_inv_stream_class = CoefficientStream_cauchy_inverse def __init__(self, base_ring, names, sparse=True, category=None): """ From a7026eab1a1cdb56141b4d125a669065556938e9 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Thu, 12 Aug 2021 10:13:24 +0200 Subject: [PATCH 5/7] fix lmul and rmul in acted_upon --- src/sage/rings/lazy_laurent_series.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/lazy_laurent_series.py b/src/sage/rings/lazy_laurent_series.py index 8664f019207..0613d9f61e7 100644 --- a/src/sage/rings/lazy_laurent_series.py +++ b/src/sage/rings/lazy_laurent_series.py @@ -824,8 +824,8 @@ def _acted_upon_(self, scalar, self_on_left): order=v, constant=c, degree=self._coeff_stream._degree)) if self_on_left or R.is_commutative(): - return P.element_class(P, CoefficientStream_rmul(self._coeff_stream, scalar)) - return P.element_class(P, CoefficientStream_lmul(self._coeff_stream, scalar)) + return P.element_class(P, CoefficientStream_lmul(self._coeff_stream, scalar)) + return P.element_class(P, CoefficientStream_rmul(self._coeff_stream, scalar)) def _neg_(self): """ From 8bb128c8cab6d2b0dff86bb328bebd61860343b2 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Aug 2021 18:55:06 +1000 Subject: [PATCH 6/7] Faster non-zero check and use LazyModuleElement for checking in __call__. --- src/sage/data_structures/coefficient_stream.py | 4 ++-- src/sage/rings/lazy_laurent_series.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/data_structures/coefficient_stream.py b/src/sage/data_structures/coefficient_stream.py index d4a8d9eb815..3de334fc1d0 100644 --- a/src/sage/data_structures/coefficient_stream.py +++ b/src/sage/data_structures/coefficient_stream.py @@ -325,7 +325,7 @@ def order(self): return n n += 1 else: - if self[n] != 0: + if self[n]: self._approximate_order = n return n n += 1 @@ -339,7 +339,7 @@ def order(self): return n n += 1 else: - if self[n] != 0: + if self[n]: self._approximate_order = n return n n += 1 diff --git a/src/sage/rings/lazy_laurent_series.py b/src/sage/rings/lazy_laurent_series.py index 0613d9f61e7..35355c1a7ef 100644 --- a/src/sage/rings/lazy_laurent_series.py +++ b/src/sage/rings/lazy_laurent_series.py @@ -1462,8 +1462,8 @@ def __call__(self, g): return self # g = 0 case - if ((not isinstance(g, LazyLaurentSeries) and not g) - or (isinstance(g, LazyLaurentSeries) + if ((not isinstance(g, LazyModuleElement) and not g) + or (isinstance(g, LazyModuleElement) and isinstance(g._coeff_stream, CoefficientStream_zero))): if self._coeff_stream._approximate_order >= 0: return P(self[0]) From 3566076bec76a886c12eac05413e51e5d089c394 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Thu, 12 Aug 2021 10:58:42 +0200 Subject: [PATCH 7/7] fix lmul and rmul doctests --- src/sage/rings/lazy_laurent_series.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/lazy_laurent_series.py b/src/sage/rings/lazy_laurent_series.py index 35355c1a7ef..8b21a50ff6d 100644 --- a/src/sage/rings/lazy_laurent_series.py +++ b/src/sage/rings/lazy_laurent_series.py @@ -734,14 +734,14 @@ def _acted_upon_(self, scalar, self_on_left): sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] sage: type(O._coeff_stream) - + sage: M * 1 is M True sage: M * 0 == 0 True sage: O = 2 * M sage: type(O._coeff_stream) - + sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] sage: 1 * M is M @@ -757,14 +757,14 @@ def _acted_upon_(self, scalar, self_on_left): sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] sage: type(O._coeff_stream) - + sage: M * 1 is M True sage: M * 0 == 0 True sage: O = 2 * M sage: type(O._coeff_stream) - + sage: O[0:10] [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] sage: 1 * M is M