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

Commit

Permalink
fix arithmetic product with 0 and finite support
Browse files Browse the repository at this point in the history
  • Loading branch information
mantepse committed Sep 3, 2022
1 parent 8b6a752 commit f88a5c8
Showing 1 changed file with 41 additions and 17 deletions.
58 changes: 41 additions & 17 deletions src/sage/rings/lazy_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,10 @@
from sage.functions.other import factorial
from sage.arith.power import generic_power
from sage.arith.functions import lcm
from sage.arith.misc import divisors, moebius, gcd
from sage.arith.misc import divisors, moebius
from sage.combinat.partition import Partition, Partitions
from sage.misc.misc_c import prod
from sage.misc.derivative import derivative_parse
from sage.combinat.partition import Partition
from sage.rings.infinity import infinity
from sage.rings.integer_ring import ZZ
from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing
Expand Down Expand Up @@ -4954,14 +4953,25 @@ def arithmetic_product(self, *args, check=True):
TESTS:
Check that the arithmetic product of symmetric functions of
finite support works::
Check that the product with zero works::
sage: s = SymmetricFunctions(QQ).s()
sage: L = LazySymmetricFunctions(s)
sage: L(0).arithmetic_product(s[2])
0
sage: L(s[2]).arithmetic_product(0)
0
Check that the arithmetic product of symmetric functions of
finite support works::
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] + 2*s[4, 1, 1]
sage: f = 1/(1-L(s[1]))
sage: f.arithmetic_product(s[1]) - f
O^7
Check the arithmetic product of symmetric functions over a
finite field works::
Expand All @@ -4979,18 +4989,17 @@ def arithmetic_product(self, *args, check=True):
or not g for g in args):
raise ValueError("all arguments must be (possibly lazy) symmetric functions")

# f = 0 or g = (0, ..., 0)
if (isinstance(self._coeff_stream, Stream_zero)
or all((not isinstance(h, LazyModuleElement) and not h)
or (isinstance(h, LazyModuleElement)
and isinstance(h._coeff_stream, Stream_zero))
for h in args)):
return P.zero()

if len(args) == 1:
g = args[0]
P = g.parent()

# f = 0 or g = (0, ..., 0)
if (isinstance(self._coeff_stream, Stream_zero)
or (not isinstance(g, LazyModuleElement) and not g)
or (isinstance(g, LazyModuleElement)
and isinstance(g._coeff_stream, Stream_zero))):
return P.zero()

if (isinstance(self._coeff_stream, Stream_exact)
and not self._coeff_stream._constant):

Expand All @@ -5012,18 +5021,33 @@ def arithmetic_product(self, *args, check=True):
P = LazySymmetricFunctions(R)
g = P(g)

# compute the constant term in the case where not both f
# and g have finite support
# TODO: this should be done lazily if possible
c = R.zero()
if self[0]:
if (isinstance(g._coeff_stream, Stream_exact)
and not g._coeff_stream._constant):
gs = g.symmetric_function()
c += self[0].arithmetic_product(gs)
elif check:
raise ValueError("can only take the arithmetic product with a positive valuation series")
if g[0]:
if (isinstance(self._coeff_stream, Stream_exact)
and not self._coeff_stream._constant):
fs = self.symmetric_function()
c += fs.arithmetic_product(g[0])
elif check:
raise ValueError("can only take the arithmetic product with a positive valuation series")

p = R.realization_of().p()
# TODO: does the following introduce a memory leak?
g = Stream_map_coefficients(g._coeff_stream, p)
f = Stream_map_coefficients(self._coeff_stream, p)

if check:
assert not f[0]
assert not g[0]

def coefficient(n):
if not n:
return R.zero()
return c
index_set = ((d, n // d) for d in divisors(n))
return sum(f[i].arithmetic_product(g[j])
for i, j in index_set if f[i] and g[j])
Expand Down

0 comments on commit f88a5c8

Please sign in to comment.