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

Commit

Permalink
Merge branch 'u/tscrim/dense_lls-31897' of git://trac.sagemath.org/sa…
Browse files Browse the repository at this point in the history
…ge into t/32324/lazy_taylor_series

* 'u/tscrim/dense_lls-31897' of git://trac.sagemath.org/sage:
  Remove revert() so it can go on a followup ticket.
  Optimizing CS_exact.polynomial_part() and other cleanup.
  Allowing tuple input for other polynomials.
  Allowing tuple as input for integer dense polynomials.
  Fixing bug with add/sub with 0. Better some_elements() and constant. Other misc tweaks.
  Fixing small bug in UnitalAlgebras.ParentMethods._coerce_map_from_base_ring().
  • Loading branch information
mantepse committed Aug 9, 2021
2 parents d379b14 + 29e139d commit 313cd4d
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/sage/categories/unital_algebras.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def _coerce_map_from_base_ring(self):
if from_base_ring.__func__ != generic_from_base_ring:
# Custom from_base_ring()
use_from_base_ring = True
if isinstance(generic_from_base_ring, lazy_attribute):
elif isinstance(generic_from_base_ring, lazy_attribute):
# If the category implements from_base_ring() as lazy
# attribute, then we always use it.
# This is for backwards compatibility, see Trac #25181
Expand Down
13 changes: 6 additions & 7 deletions src/sage/data_structures/coefficient_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@
AUTHORS:
- Kwankyu Lee (2019-02-24): initial version
- Tejasvi Chebrolu (2021-08): refactored and expanded functionality
- Tejasvi Chebrolu, Martin Rubey, Travis Scrimshaw (2021-08):
refactored and expanded functionality
"""

# ****************************************************************************
Expand Down Expand Up @@ -513,21 +513,20 @@ def __eq__(self, other):
and self._initial_coefficients == other._initial_coefficients
and self._constant == other._constant)

def polynomial_part(self, gen):
def polynomial_part(self, R):
"""
Return the initial part of ``self`` as a polynomial in ``gen``.
Return the initial part of ``self`` as a Laurent polynomial in ``R``.
EXAMPLES::
sage: from sage.data_structures.coefficient_stream import CoefficientStream_exact
sage: s = CoefficientStream_exact([2], False, valuation=-1, degree=2, constant=1)
sage: L.<z> = LazyLaurentSeriesRing(ZZ)
sage: s.polynomial_part(z)
sage: s.polynomial_part(L._laurent_poly_ring)
2*z^-1
"""
R = gen.parent()
v = self._approximate_valuation
return R(sum(val * gen**(v+i) for i, val in enumerate(self._initial_coefficients)))
return R(self._initial_coefficients).shift(v)


class CoefficientStream_coefficient_function(CoefficientStream_inexact):
Expand Down
63 changes: 51 additions & 12 deletions src/sage/rings/lazy_laurent_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@
AUTHORS:
- Kwankyu Lee (2019-02-24): initial version
- Tejasvi Chebrolu (2021-08): refactored and expanded functionality
- Tejasvi Chebrolu, Martin Rubey, Travis Scrimshaw (2021-08):
refactored and expanded functionality
"""

Expand Down Expand Up @@ -302,6 +303,7 @@ def map_coefficients(self, func, ring=None):
"""
P = self.parent()
coeff_stream = self._coeff_stream
BR = P.base_ring()
if isinstance(coeff_stream, CoefficientStream_exact):
initial_coefficients = [func(i) if i else 0
for i in coeff_stream._initial_coefficients]
Expand All @@ -312,7 +314,7 @@ def map_coefficients(self, func, ring=None):
self._coeff_stream._is_sparse,
valuation=coeff_stream._approximate_valuation,
degree=coeff_stream._degree,
constant=c)
constant=BR(c))
return P.element_class(P, coeff_stream)
coeff_stream = CoefficientStream_map_coefficients(self._coeff_stream, func, P._coeff_ring)
return P.element_class(P, coeff_stream)
Expand Down Expand Up @@ -885,6 +887,12 @@ def _add_(self, other):
sage: O[0:10]
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0]
Adding zero gives the same series::
sage: M = L(lambda n: 1 + n, valuation=0)
sage: M + 0 is 0 + M is M
True
Similarly for Dirichlet series::
sage: L = LazyDirichletSeriesRing(ZZ, "z")
Expand All @@ -911,6 +919,10 @@ def _add_(self, other):
P = self.parent()
left = self._coeff_stream
right = other._coeff_stream
if isinstance(left, CoefficientStream_zero):
return other
if isinstance(right, CoefficientStream_zero):
return self
if (isinstance(left, CoefficientStream_exact)
and isinstance(right, CoefficientStream_exact)):
approximate_valuation = min(left.valuation(), right.valuation())
Expand Down Expand Up @@ -967,10 +979,22 @@ def _sub_(self, other):
sage: O = M - L.one() - N
sage: O
0
Subtraction with 0::
sage: M = L(lambda n: 1 + n, valuation=0)
sage: M - 0 is M
True
sage: 0 - M == -M
True
"""
P = self.parent()
left = self._coeff_stream
right = other._coeff_stream
if isinstance(left, CoefficientStream_zero):
return P.element_class(P, CoefficientStream_neg(right))
if isinstance(right, CoefficientStream_zero):
return self
if (isinstance(left, CoefficientStream_exact) and isinstance(right, CoefficientStream_exact)):
approximate_valuation = min(left.valuation(), right.valuation())
degree = max(left._degree, right._degree)
Expand Down Expand Up @@ -1508,13 +1532,19 @@ def _div_(self, other):
and isinstance(right, CoefficientStream_exact)):
if not left._constant and not right._constant:
R = P._laurent_poly_ring
z = R.gen()
pl = self.finite_part()
pr = other.finite_part()
pl = left.polynomial_part(R)
pr = right.polynomial_part(R)
# pl = self.finite_part()
# pr = other.finite_part()
try:
# ret = pl / pr
# ret = P._laurent_poly_ring(ret)
# return P(ret)
ret = pl / pr
ret = P._laurent_poly_ring(ret)
return P(ret)
initial_coefficients = [ret[i] for i in range(ret.valuation(), ret.degree() + 1)]
return P.element_class(P, CoefficientStream_exact(initial_coefficients, P._sparse,
valuation=ret.valuation(), constant=left._constant))
except (TypeError, ValueError, NotImplementedError):
# We cannot divide the polynomials, so the result must be a series
pass
Expand Down Expand Up @@ -1581,7 +1611,13 @@ def __pow__(self, n):
and not cs._constant and n in ZZ
and (n > 0 or len(cs._initial_coefficients) == 1)):
P = self.parent()
return P(self.finite_part() ** ZZ(n))
# return P(self.finite_part() ** ZZ(n))
ret = cs.polynomial_part(P._laurent_poly_ring) ** ZZ(n)
val = ret.valuation()
deg = ret.degree() + 1
initial_coefficients = [ret[i] for i in range(val, deg)]
return P.element_class(P, CoefficientStream_exact(initial_coefficients, P._sparse,
constant=cs._constant, degree=deg, valuation=val))

return generic_power(self, n)

Expand Down Expand Up @@ -1744,7 +1780,7 @@ def __call__(self, g):
sage: g = 1 - y
sage: f(g)
3 - y + 2*y^2 + y^3 + y^4 + y^5 + y^6 + O(y^7)
3 - y + 2*y^2 + y^3 + y^4 + y^5 + O(y^6)
sage: g^2 + 1 + g^-1
3 - y + 2*y^2 + y^3 + y^4 + y^5 + O(y^6)
Expand Down Expand Up @@ -1882,15 +1918,15 @@ def __call__(self, g):
# constant polynomial
R = self.parent()._laurent_poly_ring
z = R.gen()
poly = self._coeff_stream.polynomial_part(z)
poly = self._coeff_stream.polynomial_part(R)
if poly.is_constant():
return self
if not isinstance(g, LazyLaurentSeries):
return poly(g)
# g also has finite length, compose the polynomials
if isinstance(g._coeff_stream, CoefficientStream_exact) and not g._coeff_stream._constant:
R = P._laurent_poly_ring
g_poly = g._coeff_stream.polynomial_part(R.gen())
g_poly = g._coeff_stream.polynomial_part(R)
try:
ret = poly(g_poly)
except (ValueError, TypeError): # the result is not a Laurent polynomial
Expand All @@ -1899,7 +1935,10 @@ def __call__(self, g):
val = ret.valuation()
deg = ret.degree() + 1
initial_coefficients = [ret[i] for i in range(val, deg)]
return P.element_class(P, CoefficientStream_exact(initial_coefficients, self._coeff_stream._is_sparse, 0, deg, val))
coeff_stream = CoefficientStream_exact(initial_coefficients,
self._coeff_stream._is_sparse, constant=P.base_ring().zero(),
degree=deg, valuation=val)
return P.element_class(P, coeff_stream)

# Return the sum since g is not known to be finite or we do not get a Laurent polynomial
# TODO: Optimize when f has positive valuation
Expand Down Expand Up @@ -2116,7 +2155,7 @@ def _format_series(self, formatter, format_strings=False):
strformat = lambda x: x

if isinstance(cs, CoefficientStream_exact):
poly = cs.polynomial_part(z)
poly = cs.polynomial_part(R)
if not cs._constant:
return formatter(poly)
m = cs._degree + P.options.constant_length
Expand Down
Loading

0 comments on commit 313cd4d

Please sign in to comment.