From 0de1c13a55bc168b6c7a1fc0411a5f81b28dbf88 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 9 Sep 2022 08:14:07 +0200 Subject: [PATCH 1/9] add a warning and an example for the arithmetic product with a constant term --- src/sage/rings/lazy_series.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index b01a5f4cf6d..068e57a13f9 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -4877,6 +4877,14 @@ def arithmetic_product(self, *args, check=True): http://mathoverflow.net/questions/138148/ for a discussion of this arithmetic product. + .. WARNING:: + + The operation `f \boxdot g` was originally defined only + for symmetric functions `f` and `g` without constant + term. We extend this definition using the convention + that the least common multiple of any integer with `0` is + `0`. + If `f` and `g` are two symmetric functions which are homogeneous of degrees `a` and `b`, respectively, then `f \boxdot g` is homogeneous of degree `ab`. @@ -4972,6 +4980,14 @@ def arithmetic_product(self, *args, check=True): sage: f.arithmetic_product(s[1]) - f O^7 + Check that the arithmetic product of symmetric functions with +constant a term works as advertised:: + + sage: p = SymmetricFunctions(QQ).p() + sage: L = LazySymmetricFunctions(p) + sage: L(5).arithmetic_product(3*p[2,1]) + 15*p[] + Check the arithmetic product of symmetric functions over a finite field works:: @@ -4979,7 +4995,6 @@ def arithmetic_product(self, *args, check=True): sage: L = LazySymmetricFunctions(s) sage: L(s([2])).arithmetic_product(s([1,1,1])) s[2, 2, 1, 1] + s[3, 1, 1, 1] + s[3, 2, 1] + s[3, 3] - """ if len(args) != self.parent()._arity: raise ValueError("arity must be equal to the number of arguments provided") From 8e5de35ee5f302a46f1af008d1e06f62bdf37f7b Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 9 Sep 2022 08:53:11 +0200 Subject: [PATCH 2/9] add missing whitespace in docstring --- src/sage/rings/lazy_series.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 068e57a13f9..5e2994d082b 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -4981,7 +4981,7 @@ def arithmetic_product(self, *args, check=True): O^7 Check that the arithmetic product of symmetric functions with -constant a term works as advertised:: + constant a term works as advertised:: sage: p = SymmetricFunctions(QQ).p() sage: L = LazySymmetricFunctions(p) @@ -4995,6 +4995,7 @@ def arithmetic_product(self, *args, check=True): sage: L = LazySymmetricFunctions(s) sage: L(s([2])).arithmetic_product(s([1,1,1])) s[2, 2, 1, 1] + s[3, 1, 1, 1] + s[3, 2, 1] + s[3, 3] + """ if len(args) != self.parent()._arity: raise ValueError("arity must be equal to the number of arguments provided") From f5e3f2ef6f0c1757881e16c1563833cf119f4a83 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 9 Sep 2022 12:46:04 +0200 Subject: [PATCH 3/9] fix documentation --- src/doc/en/reference/combinat/module_list.rst | 3 -- src/sage/combinat/tutorial.py | 2 +- src/sage/rings/lazy_series_ring.py | 34 +++++++++++-------- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 7a97a40e30d..e42e3891d45 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -339,11 +339,8 @@ Comprehensive Module List sage/combinat/species/permutation_species sage/combinat/species/product_species sage/combinat/species/recursive_species - sage/combinat/species/series - sage/combinat/species/series_order sage/combinat/species/set_species sage/combinat/species/species - sage/combinat/species/stream sage/combinat/species/structure sage/combinat/species/subset_species sage/combinat/species/sum_species diff --git a/src/sage/combinat/tutorial.py b/src/sage/combinat/tutorial.py index 90ec8eea713..6422d920378 100644 --- a/src/sage/combinat/tutorial.py +++ b/src/sage/combinat/tutorial.py @@ -310,7 +310,7 @@ It is unfortunate to have to recalculate everything if at some point we wanted the 101-st coefficient. Lazy power series (see -:mod:`sage.combinat.species.series`) come into their own here, in that +:mod:`sage.rings.lazy_series_ring`) come into their own here, in that one can define them from a system of equations without solving it, and, in particular, without needing a closed form for the answer. We begin by defining the ring of lazy power series:: diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index c29a41fcd1c..78299f03c17 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -709,7 +709,7 @@ def is_exact(self): class LazyLaurentSeriesRing(LazySeriesRing): - """ + r""" The ring of lazy Laurent series. The ring of Laurent series over a ring with the usual arithmetic @@ -743,8 +743,7 @@ class LazyLaurentSeriesRing(LazySeriesRing): Finite Field of size 3 Series can be defined by specifying a coefficient function - along with a valuation or a degree where after the series - is evenutally constant:: + and a valuation:: sage: R. = QQ[] sage: L. = LazyLaurentSeriesRing(R) @@ -764,9 +763,9 @@ class LazyLaurentSeriesRing(LazySeriesRing): -5*z^-3 - 4*z^-2 - 3*z^-1 + 6 + (x + y)*z + (y^2 + x)*z^2 + x*z^3 + x*z^4 + x*z^5 + O(z^6) - Similarly, we can specify a polynomial or the initial - coefficients with anything that converts into the - corresponding Laurent polynomial ring:: + We can also specify a polynomial or the initial coefficients. + Additionally, we may specify that all coefficients are equal to a + given constant, beginning at a given degree:: sage: L([1, x, y, 0, x+y]) 1 + x*z + y*z^2 + (x + y)*z^4 @@ -797,8 +796,8 @@ class LazyLaurentSeriesRing(LazySeriesRing): sage: L(x^-2 + 3 + x, valuation=-5, degree=0, constant=2) z^-5 + 3*z^-3 + z^-2 + 2 + 2*z + 2*z^2 + O(z^3) - We can also truncate, shift, and make eventually constant any - Laurent series:: + We can truncate a series, shift its coefficients, or replace all + coefficients beginning with a given degree by a constant:: sage: f = 1 / (z + z^2) sage: f @@ -819,16 +818,16 @@ class LazyLaurentSeriesRing(LazySeriesRing): more examples):: sage: L. = LazyLaurentSeriesRing(ZZ) - sage: s = L(None, valuation=0) + sage: s = L.undefined(valuation=0) sage: s.define(1 + z*s^2) sage: s 1 + z + 2*z^2 + 5*z^3 + 14*z^4 + 42*z^5 + 132*z^6 + O(z^7) - If we do not explicitly know the exact value of every - coefficient, then equality checking will depend on the computed - coefficients. If at a certain point we cannot prove two series - are different (which involves the coefficients we have computed), - then we will raise an error:: + If the series is not specified by a finite number of initial + coefficients and a constant for the remaining coefficients, then + equality checking will depend on the coefficients which have + already been computed. If this information is not enough to + check that two series are different we raise an error:: sage: f = 1 / (z + z^2); f z^-1 - 1 + z - z^2 + z^3 - z^4 + z^5 + O(z^6) @@ -1302,6 +1301,13 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No - ``degree`` -- (optional) the degree when the series is ``constant`` - ``check`` -- (optional) check that coefficients are homogeneous of the correct degree when they are retrieved + .. WARNING:: + + The behaviour of ``LazyPowerSeries(l)`` for a list ``l`` + with non-zero last element `e` changed with + :trac:`32367`. To obtain the old behaviour, use + ``LazyPowerSeries(l, constant=e)``. + EXAMPLES:: sage: L = LazyPowerSeriesRing(GF(2), 'z') From c5bfba5f8e8d41bc6341b7a490ae56469e2adcae Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Fri, 9 Sep 2022 20:26:44 +0200 Subject: [PATCH 4/9] adapt a doctest --- src/sage/combinat/sf/sfa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 1fb9d204e34..854b92393f5 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -3083,7 +3083,7 @@ def plethysm(self, x, include=None, exclude=None): + ... + O^8 sage: fog = f(g) sage: fog[:8] - [s[2, 1], + [0, 0, 0, s[2, 1], s[1, 1, 1, 1] + 3*s[2, 1, 1] + 2*s[2, 2] + 3*s[3, 1] + s[4], 2*s[1, 1, 1, 1, 1] + 8*s[2, 1, 1, 1] + 10*s[2, 2, 1] + 12*s[3, 1, 1] + 10*s[3, 2] + 8*s[4, 1] + 2*s[5], From ceecc89392820fbbf07f2ad1b9915ac02ac4d6d4 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 10 Sep 2022 08:20:09 +0200 Subject: [PATCH 5/9] don't use l --- src/sage/rings/lazy_series_ring.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index 78299f03c17..98e40a41c8f 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -1303,10 +1303,10 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No .. WARNING:: - The behaviour of ``LazyPowerSeries(l)`` for a list ``l`` + The behaviour of ``LazyPowerSeries(c)`` for a list ``c`` with non-zero last element `e` changed with :trac:`32367`. To obtain the old behaviour, use - ``LazyPowerSeries(l, constant=e)``. + ``LazyPowerSeries(c, constant=e)``. EXAMPLES:: From 9629b2878b228fb2c5623f4d2b1df60e2c4bb287 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 10 Sep 2022 08:46:45 +0200 Subject: [PATCH 6/9] require the start value for __getitem__ of LazyLaurentSeries --- src/sage/rings/lazy_series.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index e7869d6e8b5..f6079c16210 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -204,9 +204,9 @@ class LazyModuleElement(Element): sage: L. = LazyLaurentSeriesRing(ZZ) sage: M = L(lambda n: n, valuation=0) sage: N = L(lambda n: 1, valuation=0) - sage: M[:10] + sage: M[0:10] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - sage: N[:10] + sage: N[0:10] [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] Two sequences can be added:: @@ -218,19 +218,19 @@ class LazyModuleElement(Element): Two sequences can be subtracted:: sage: P = M - N - sage: P[:10] + sage: P[0:10] [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8] A sequence can be multiplied by a scalar:: sage: Q = 2 * M - sage: Q[:10] + sage: Q[0:10] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18] The negation of a sequence can also be found:: sage: R = -M - sage: R[:10] + sage: R[0:10] [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] """ def __init__(self, parent, coeff_stream): @@ -304,7 +304,7 @@ def __getitem__(self, n): elif L._minimal_valuation is not None: start = L._minimal_valuation else: - start = self._coeff_stream._approximate_order + raise ValueError("the start value must be specified if there is no minimal valuation, such as for LazyLaurentSeries") step = n.step if n.step is not None else 1 return [R(self._coeff_stream[k]) for k in range(start, n.stop, step)] return R(self._coeff_stream[n]) @@ -739,9 +739,9 @@ def define(self, s): sage: t = L(None, valuation=0) sage: s.define(1 + z*t^3) sage: t.define(1 + z*s^2) - sage: s[:9] + sage: s[0:9] [1, 1, 3, 9, 34, 132, 546, 2327, 10191] - sage: t[:9] + sage: t[0:9] [1, 1, 2, 7, 24, 95, 386, 1641, 7150] A bigger example:: @@ -765,7 +765,7 @@ def define(self, s): sage: L. = LazyLaurentSeriesRing(QQ) sage: s = L(None, valuation=1) sage: s.define(z + (s^2+s(z^2))/2) - sage: [s[i] for i in range(9)] + sage: s[0:9] [0, 1, 1, 1, 2, 3, 6, 11, 23] The `q`-Catalan numbers:: @@ -791,7 +791,7 @@ def define(self, s): sage: L = Q(constant=1, degree=1) sage: T = Q(None, valuation=1) sage: T.define(leaf + internal_node * L(T)) - sage: [T[i] for i in range(6)] + sage: T[0:6] [0, 1, q, q^2 + q, q^3 + 3*q^2 + q, q^4 + 6*q^3 + 6*q^2 + q] Similarly for Dirichlet series:: @@ -799,7 +799,7 @@ def define(self, s): sage: L = LazyDirichletSeriesRing(ZZ, "z") sage: g = L(constant=1, valuation=2) sage: F = L(None); F.define(1 + g*F) - sage: [F[i] for i in range(1, 16)] + sage: F[:16] [1, 1, 1, 2, 1, 3, 1, 4, 2, 3, 1, 8, 1, 3, 3] sage: oeis(_) # optional, internet 0: A002033: Number of perfect partitions of n. @@ -807,7 +807,7 @@ def define(self, s): ... sage: F = L(None); F.define(1 + g*F*F) - sage: [F[i] for i in range(1, 16)] + sage: F[:16] [1, 1, 1, 3, 1, 5, 1, 10, 3, 5, 1, 24, 1, 5, 5] We can compute the Frobenius character of unlabeled trees:: @@ -831,7 +831,7 @@ def define(self, s): sage: L. = LazyLaurentSeriesRing(ZZ, sparse=True) sage: s = L(None, valuation=0) sage: s.define(1 + z*s^3) - sage: s[:10] + sage: s[0:10] [1, 1, 3, 12, 55, 273, 1428, 7752, 43263, 246675] sage: e = L(None, valuation=0) From 037f3f7cad9b7bfb955f9cb3d1aaf7a4363c7ccb Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 10 Sep 2022 10:36:32 +0200 Subject: [PATCH 7/9] implement coefficients --- src/sage/rings/lazy_series.py | 61 +++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index f6079c16210..4eadf1cece3 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -311,6 +311,67 @@ def __getitem__(self, n): coefficient = __getitem__ + def coefficients(self, n=None): + """ + Return the first `n` non-zero coefficients of self. + + EXAMPLES:: + + sage: L. = LazyPowerSeriesRing(QQ) + sage: f = L([1,2,3]) + sage: f.coefficients(5) + doctest:...: DeprecationWarning: the method coefficients now only returns the non-zero coefficients. Use __getitem__ instead. + See https://trac.sagemath.org/32367 for details. + [1, 2, 3] + + sage: f = sin(x) + sage: f.coefficients(5) + doctest:...: DeprecationWarning: the method coefficients now only returns the non-zero coefficients. Use __getitem__ instead. + See https://trac.sagemath.org/32367 for details. + [1, -1/6, 1/120, -1/5040, 1/362880] + + sage: L. = LazyPowerSeriesRing(QQ) + sage: f = sin(x^2+y^2) + sage: f.coefficients(5) + """ + coeff_stream = self._coeff_stream + if isinstance(coeff_stream, Stream_zero): + return [] + + if n is None: + from sage.misc.lazy_list import lazy_list + if isinstance(coeff_stream, Stream_exact): + if coeff_stream._constant: + coeffs = ([c for c in coeff_stream._initial_coefficients if c] + + lazy_list(lambda n: coeff_stream._constant)) + else: + coeffs = [c for c in coeff_stream._initial_coefficients if c] + else: + coeffs = lazy_list(filter(lambda c: c, + coeff_stream.iterate_coefficients())) + else: + if isinstance(self, LazyPowerSeries) and self.parent()._arity == 1: + from sage.misc.superseded import deprecation + deprecation(32367, 'the method coefficients now only returns the non-zero coefficients. Use __getitem__ instead.') + + if isinstance(coeff_stream, Stream_exact) and not coeff_stream._constant: + coeffs = [c for c in coeff_stream._initial_coefficients if c] + else: + coeffs = [] + i = self.valuation() + while len(coeffs) < n: + if self[i]: + coeffs.append(self[i]) + i += 1 + + if self.base_ring() == self.parent()._internal_poly_ring.base_ring(): + return coeffs + + if isinstance(coeffs, list): + return [c for coeff in coeffs for c in coeff.coefficients()] + + return lazy_list(map(lambda coeff: coeff.coefficients(), coeffs)) + def map_coefficients(self, func): r""" Return the series with ``func`` applied to each nonzero From 787197ed609f8291ba23d2c102686b2d8353ec9d Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sat, 10 Sep 2022 16:07:35 +0200 Subject: [PATCH 8/9] fix some bugs --- src/sage/rings/lazy_series.py | 79 ++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 33 deletions(-) diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 4eadf1cece3..9658f98252a 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -312,8 +312,24 @@ def __getitem__(self, n): coefficient = __getitem__ def coefficients(self, n=None): - """ - Return the first `n` non-zero coefficients of self. + r"""Return the first `n` non-zero coefficients of ``self``. + + INPUT: + + - ``n`` -- (default: ``None``), the number of non-zero + coefficients to return. + + If the series has fewer than `n` non-zero coefficients, only + these are returned. + + If ``n`` is ``None``, a + :class:`~sage.misc.lazy_list.lazy_list_generic` with all + non-zero coefficients is returned instead. + + .. WARNING:: + + If there are fewer than `n` non-zero coefficients, but + this cannot be detected, this method will not return. EXAMPLES:: @@ -326,51 +342,48 @@ def coefficients(self, n=None): sage: f = sin(x) sage: f.coefficients(5) - doctest:...: DeprecationWarning: the method coefficients now only returns the non-zero coefficients. Use __getitem__ instead. - See https://trac.sagemath.org/32367 for details. [1, -1/6, 1/120, -1/5040, 1/362880] sage: L. = LazyPowerSeriesRing(QQ) sage: f = sin(x^2+y^2) - sage: f.coefficients(5) + sage: f.coefficients(5) + [1, 1, -1/6, -1/2, -1/2] + + sage: f.coefficients() + lazy list [1, 1, -1/6, ...] + """ coeff_stream = self._coeff_stream if isinstance(coeff_stream, Stream_zero): return [] - - if n is None: - from sage.misc.lazy_list import lazy_list - if isinstance(coeff_stream, Stream_exact): - if coeff_stream._constant: - coeffs = ([c for c in coeff_stream._initial_coefficients if c] - + lazy_list(lambda n: coeff_stream._constant)) - else: - coeffs = [c for c in coeff_stream._initial_coefficients if c] + from itertools import repeat, chain, islice + from sage.misc.lazy_list import lazy_list + # prepare a generator of the non-zero coefficients + if isinstance(coeff_stream, Stream_exact): + if coeff_stream._constant: + coeffs = chain([c for c in coeff_stream._initial_coefficients if c], + repeat(coeff_stream._constant)) else: - coeffs = lazy_list(filter(lambda c: c, - coeff_stream.iterate_coefficients())) + coeffs = (c for c in coeff_stream._initial_coefficients if c) else: - if isinstance(self, LazyPowerSeries) and self.parent()._arity == 1: - from sage.misc.superseded import deprecation - deprecation(32367, 'the method coefficients now only returns the non-zero coefficients. Use __getitem__ instead.') + coeffs = filter(lambda c: c, coeff_stream.iterate_coefficients()) - if isinstance(coeff_stream, Stream_exact) and not coeff_stream._constant: - coeffs = [c for c in coeff_stream._initial_coefficients if c] - else: - coeffs = [] - i = self.valuation() - while len(coeffs) < n: - if self[i]: - coeffs.append(self[i]) - i += 1 + if n is None: + if self.base_ring() == self.parent()._internal_poly_ring.base_ring(): + return lazy_list(coeffs) - if self.base_ring() == self.parent()._internal_poly_ring.base_ring(): - return coeffs + # flatten out the generator in the multivariate case + return lazy_list(chain.from_iterable(map(lambda coeff: coeff.coefficients(), coeffs))) + + if isinstance(self, LazyPowerSeries) and self.parent()._arity == 1: + from sage.misc.superseded import deprecation + deprecation(32367, 'the method coefficients now only returns the non-zero coefficients. Use __getitem__ instead.') - if isinstance(coeffs, list): - return [c for coeff in coeffs for c in coeff.coefficients()] + if self.base_ring() == self.parent()._internal_poly_ring.base_ring(): + return list(islice(coeffs, n)) - return lazy_list(map(lambda coeff: coeff.coefficients(), coeffs)) + # flatten out the generator in the multivariate case + return list(islice(chain.from_iterable(map(lambda coeff: coeff.coefficients(), coeffs)), n)) def map_coefficients(self, func): r""" From 8f46e127e30e1f0a3e6d1a6997e806baf7254710 Mon Sep 17 00:00:00 2001 From: Martin Rubey Date: Sun, 11 Sep 2022 19:48:40 +0200 Subject: [PATCH 9/9] implement new semantics of __getitem__ --- src/sage/combinat/sf/sfa.py | 2 +- src/sage/rings/lazy_series.py | 68 ++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 854b92393f5..1fb9d204e34 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -3083,7 +3083,7 @@ def plethysm(self, x, include=None, exclude=None): + ... + O^8 sage: fog = f(g) sage: fog[:8] - [0, 0, 0, s[2, 1], + [s[2, 1], s[1, 1, 1, 1] + 3*s[2, 1, 1] + 2*s[2, 2] + 3*s[3, 1] + s[4], 2*s[1, 1, 1, 1, 1] + 8*s[2, 1, 1, 1] + 10*s[2, 2, 1] + 12*s[3, 1, 1] + 10*s[3, 2] + 8*s[4, 1] + 2*s[5], diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 9658f98252a..0b3567830c4 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -251,21 +251,36 @@ def __init__(self, parent, coeff_stream): self._coeff_stream = coeff_stream def __getitem__(self, n): - """ - Return the coefficient of the term with exponent ``n`` of the series. + r""" + Return the homogeneous degree ``n`` part of the series. INPUT: - - ``n`` -- integer; the exponent + - ``n`` -- integer; the degree + + For a series ``f``, the slice ``f[start:stop]`` produces the following: + + - if ``start`` and ``stop`` are integers, return the list of + terms with given degrees + + - if ``start`` is ``None``, return the list of terms + beginning with the valuation + + - if ``stop`` is ``None``, return a + :class:`~sage.misc.lazy_list.lazy_list_generic` instead. EXAMPLES:: - sage: L. = LazyLaurentSeriesRing(ZZ, sparse=False) + sage: L. = LazyLaurentSeriesRing(ZZ) sage: f = z / (1 - 2*z^3) sage: [f[n] for n in range(20)] [0, 1, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, 0, 16, 0, 0, 32, 0, 0, 64] sage: f[0:20] [0, 1, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, 0, 16, 0, 0, 32, 0, 0, 64] + sage: f[:20] + [1, 0, 0, 2, 0, 0, 4, 0, 0, 8, 0, 0, 16, 0, 0, 32, 0, 0, 64] + sage: f[::3] + lazy list [1, 2, 4, ...] sage: M = L(lambda n: n, valuation=0) sage: [M[n] for n in range(20)] @@ -276,37 +291,35 @@ def __getitem__(self, n): sage: [M[n] for n in range(20)] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19] + Similarly for multivariate series:: + + sage: L. = LazyPowerSeriesRing(QQ) + sage: sin(x*y)[:11] + [x*y, 0, 0, 0, -1/6*x^3*y^3, 0, 0, 0, 1/120*x^5*y^5] + sage: sin(x*y)[2::4] + lazy list [x*y, -1/6*x^3*y^3, 1/120*x^5*y^5, ...] + Similarly for Dirichlet series:: sage: L = LazyDirichletSeriesRing(ZZ, "z") - sage: f = L(lambda n: n) - sage: [f[n] for n in range(1, 11)] - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - sage: f[1:11] + sage: L(lambda n: n)[1:11] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - - sage: M = L(lambda n: n) - sage: [M[n] for n in range(1, 11)] - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - sage: L = LazyDirichletSeriesRing(ZZ, "z", sparse=True) - sage: M = L(lambda n: n) - sage: [M[n] for n in range(1, 11)] - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - """ - L = self.parent() - R = L._internal_poly_ring.base_ring() + R = self.parent()._internal_poly_ring.base_ring() if isinstance(n, slice): - if n.stop is None: - raise NotImplementedError("cannot list an infinite set") - if n.start is not None: - start = n.start - elif L._minimal_valuation is not None: - start = L._minimal_valuation + if n.start is None: + # WARNING: for Dirichlet series, 'degree' and + # valuation are different + start = self._coeff_stream.order() else: - raise ValueError("the start value must be specified if there is no minimal valuation, such as for LazyLaurentSeries") + start = n.start step = n.step if n.step is not None else 1 + if n.stop is None: + from sage.misc.lazy_list import lazy_list + return lazy_list(lambda k: R(self._coeff_stream[start + k * step])) + return [R(self._coeff_stream[k]) for k in range(start, n.stop, step)] + return R(self._coeff_stream[n]) coefficient = __getitem__ @@ -893,8 +906,7 @@ def define(self, s): sage: X = L(s[1]) sage: A = L(None); A.define(X*E(A, check=False)) sage: A[:6] - [0, - m[1], + [m[1], 2*m[1, 1] + m[2], 9*m[1, 1, 1] + 5*m[2, 1] + 2*m[3], 64*m[1, 1, 1, 1] + 34*m[2, 1, 1] + 18*m[2, 2] + 13*m[3, 1] + 4*m[4],