Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Moving shift up and bug fixing.
Browse files Browse the repository at this point in the history
  • Loading branch information
tscrim committed Sep 21, 2021
1 parent 0f2355f commit 30d3804
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 76 deletions.
154 changes: 82 additions & 72 deletions src/sage/rings/lazy_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,88 @@ def truncate(self, d):
return P.element_class(P, Stream_exact(initial_coefficients, P._sparse,
order=v))

def shift(self, n):
r"""
Return ``self`` with the indices shifted by ``n``.
For example, a Laurent series is multiplied by the power `z^n`,
where `z` is the variable of ``self``.
EXAMPLES::
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
sage: f = 1 / (1 + 2*z)
sage: f
1 - 2*z + 4*z^2 - 8*z^3 + 16*z^4 - 32*z^5 + 64*z^6 + O(z^7)
sage: f.shift(3)
z^3 - 2*z^4 + 4*z^5 - 8*z^6 + 16*z^7 - 32*z^8 + 64*z^9 + O(z^10)
sage: f << -3 # shorthand
z^-3 - 2*z^-2 + 4*z^-1 - 8 + 16*z - 32*z^2 + 64*z^3 + O(z^4)
sage: g = z^-3 + 3 + z^2
sage: g.shift(5)
z^2 + 3*z^5 + z^7
sage: L([2,0,3], valuation=2, degree=7, constant=1) << -2
2 + 3*z^2 + z^5 + z^6 + z^7 + O(z^8)
sage: D = LazyDirichletSeriesRing(QQ, 't')
sage: f = D([0,1,2]); f
1/(2^t) + 2/3^t
sage: f.shift(3)
1/(5^t) + 2/6^t
TESTS::
sage: L.<z> = LazyLaurentSeriesRing(QQ)
sage: zero = L.zero()
sage: zero.shift(10) is zero
True
sage: f = 1 / (1 + 2*z + z^2)
sage: f.shift(5).shift(-5) - f
0
"""
if isinstance(self._coeff_stream, Stream_zero):
return self
elif isinstance(self._coeff_stream, Stream_shift):
n += self._coeff_stream._shift
if n:
coeff_stream = Stream_shift(self._coeff_stream._series, n)
else:
coeff_stream = self._coeff_stream._series
elif isinstance(self._coeff_stream, Stream_exact):
init_coeff = self._coeff_stream._initial_coefficients
degree = self._coeff_stream._degree + n
valuation = self._coeff_stream._approximate_order + n
coeff_stream = Stream_exact(init_coeff, self._coeff_stream._is_sparse,
constant=self._coeff_stream._constant,
order=valuation, degree=degree)
else:
coeff_stream = Stream_shift(self._coeff_stream, n)
P = self.parent()
return P.element_class(P, coeff_stream)

__lshift__ = shift

def __rshift__(self, n):
r"""
Return ``self`` with the indices shifted right by ``n``.
For example, a Laurent series is multiplied by the power `z^-n`,
where `z` is the variable of ``self``.
EXAMPLES::
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
sage: f = 1/(1 + 2*z); f
1 - 2*z + 4*z^2 - 8*z^3 + 16*z^4 - 32*z^5 + 64*z^6 + O(z^7)
sage: f >> 3
z^-3 - 2*z^-2 + 4*z^-1 - 8 + 16*z - 32*z^2 + 64*z^3 + O(z^4)
sage: f >> -3
z^3 - 2*z^4 + 4*z^5 - 8*z^6 + 16*z^7 - 32*z^8 + 64*z^9 + O(z^10)
"""
return self.shift(-n)

def prec(self):
"""
Return the precision of the series, which is infinity.
Expand Down Expand Up @@ -2282,78 +2364,6 @@ def polynomial(self, degree=None, name=None):
R = PolynomialRing(S.base_ring(), name=name)
return R([self[i] for i in range(m)])

def shift(self, n):
r"""
Return ``self`` multiplied by the power `z^n`, where `z` is the
variable of ``self``.
EXAMPLES::
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
sage: f = 1 / (1 + 2*z)
sage: f
1 - 2*z + 4*z^2 - 8*z^3 + 16*z^4 - 32*z^5 + 64*z^6 + O(z^7)
sage: f.shift(3)
z^3 - 2*z^4 + 4*z^5 - 8*z^6 + 16*z^7 - 32*z^8 + 64*z^9 + O(z^10)
sage: f << -3 # shorthand
z^-3 - 2*z^-2 + 4*z^-1 - 8 + 16*z - 32*z^2 + 64*z^3 + O(z^4)
sage: g = z^-3 + 3 + z^2
sage: g.shift(5)
z^2 + 3*z^5 + z^7
sage: L([2,0,3], valuation=2, degree=7, constant=1) << -2
2 + 3*z^2 + z^5 + z^6 + z^7 + O(z^8)
TESTS::
sage: L.<z> = LazyLaurentSeriesRing(QQ)
sage: zero = L.zero()
sage: zero.shift(10) is zero
True
sage: f = 1 / (1 + 2*z + z^2)
sage: f.shift(5).shift(-5) - f
0
"""
if isinstance(self._coeff_stream, Stream_zero):
return self
elif isinstance(self._coeff_stream, Stream_shift):
n += self._coeff_stream._shift
if n:
coeff_stream = Stream_shift(self._coeff_stream._series, n)
else:
coeff_stream = self._coeff_stream._series
elif isinstance(self._coeff_stream, Stream_exact):
init_coeff = self._coeff_stream._initial_coefficients
degree = self._coeff_stream._degree + n
valuation = self._coeff_stream._approximate_order + n
coeff_stream = Stream_exact(init_coeff, self._coeff_stream._is_sparse,
constant=self._coeff_stream._constant,
order=valuation, degree=degree)
else:
coeff_stream = Stream_shift(self._coeff_stream, n)
P = self.parent()
return P.element_class(P, coeff_stream)

__lshift__ = shift

def __rshift__(self, n):
r"""
Return ``self`` multiplied by the power `z^-n`, where `z` is the
variable of ``self``.
EXAMPLES::
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
sage: f = 1/(1 + 2*z); f
1 - 2*z + 4*z^2 - 8*z^3 + 16*z^4 - 32*z^5 + 64*z^6 + O(z^7)
sage: f >> 3
z^-3 - 2*z^-2 + 4*z^-1 - 8 + 16*z - 32*z^2 + 64*z^3 + O(z^4)
sage: f >> -3
z^3 - 2*z^4 + 4*z^5 - 8*z^6 + 16*z^7 - 32*z^8 + 64*z^9 + O(z^10)
"""
return self.shift(-n)

def _format_series(self, formatter, format_strings=False):
"""
Return ``self`` formatted by ``formatter``.
Expand Down
23 changes: 19 additions & 4 deletions src/sage/rings/lazy_series_ring.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No
except (TypeError, ValueError):
pass

# If x has been converted to the Laurent polynomial ring
# If x has been converted to the internal polynomial ring
if parent(x) is R:
if not x and not constant:
return self.zero()
Expand All @@ -326,7 +326,9 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No
# If x is known to be 0
if isinstance(x._coeff_stream, Stream_zero):
if not constant:
return x
if self is parent(x):
return x
return self.element_class(self, x._coeff_stream)
if degree is None:
if valuation is None:
raise ValueError("you must specify the degree for the polynomial 0")
Expand Down Expand Up @@ -356,7 +358,7 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No
ret = self.element_class(self, x._coeff_stream)
if valuation is None:
return ret
return x.shift(valuation - x._coeff_stream.order())
return ret.shift(valuation - x._coeff_stream.order())

else:
x = coefficients
Expand Down Expand Up @@ -1108,6 +1110,16 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No
...
ValueError: positive characteristic not allowed for Dirichlet series
sage: L.<z> = LazyLaurentSeriesRing(QQ)
sage: D = LazyDirichletSeriesRing(QQ, 't')
sage: D(z+z^2)
1 + 1/(2^t)
sage: R.<z> = LaurentPolynomialRing(QQ)
sage: D = LazyDirichletSeriesRing(QQ, 't')
sage: D(coefficients=z+z^2)
2 + 6/2^t + 12/3^t + 20/4^t + 30/5^t + 42/6^t + 56/7^t + O(1/(8^t))
.. TODO::
Add a method to make a copy of ``self._sparse``.
Expand All @@ -1120,12 +1132,15 @@ def _element_constructor_(self, x=None, valuation=None, degree=None, constant=No
x = p
else:
x = p.shift(1)
elif valuation is None:
elif not isinstance(x, LazyModuleElement) and valuation is None:
valuation = 1

if valuation is not None and (valuation not in ZZ or valuation <= 0):
raise ValueError("the valuation must be a positive integer")

if coefficients is not None:
return super()._element_constructor_(x, valuation, degree, constant, coefficients)

BR = self.base_ring()
if x in BR:
x = BR(x)
Expand Down

0 comments on commit 30d3804

Please sign in to comment.