Skip to content

Commit

Permalink
Merge branch 'precision_in_logexp' into caipi
Browse files Browse the repository at this point in the history
  • Loading branch information
xcaruso committed Dec 28, 2024
2 parents 5d92948 + 174d4a4 commit 5f6e2d5
Showing 1 changed file with 48 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@
from .drinfeld_module import DrinfeldModule

from sage.rings.integer_ring import ZZ
from sage.rings.infinity import Infinity

from sage.misc.cachefunc import cached_method
from sage.misc.lazy_import import lazy_import

lazy_import('sage.rings.lazy_series_ring', 'LazyPowerSeriesRing')
lazy_import('sage.rings.power_series_ring', 'PowerSeriesRing')


class DrinfeldModule_charzero(DrinfeldModule):
Expand Down Expand Up @@ -149,7 +151,7 @@ def _compute_coefficient_exp(self, k):
c += self._compute_coefficient_exp(i)*self._compute_coefficient_log(j)**(q**i)
return -c

def exponential(self, name='z'):
def exponential(self, prec=Infinity, name='z'):
r"""
Return the exponential of this Drinfeld module.
Expand All @@ -158,28 +160,37 @@ def exponential(self, name='z'):
INPUT:
- ``prec`` -- an integer or ``Infinity`` (default: ``Infinity``);
the precision at which the series is returned; if ``Infinity``,
a lazy power series in returned
- ``name`` -- string (default: ``'z'``); the name of the
generator of the lazy power series ring
OUTPUT: a lazy power series over the base field
EXAMPLES::
sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: phi = DrinfeldModule(A, [T, 1])
sage: q = A.base_ring().cardinality()
sage: exp = phi.exponential(); exp
z + ((1/(T^2+T))*z^2) + ((1/(T^8+T^6+T^5+T^3))*z^4) + O(z^8)
The exponential is returned as a lazy power series, meaning that
any of its coefficients can be computed on demands::
When ``prec`` is ``Infinity`` (which is the default),
the exponential is returned as a lazy power series, meaning
that any of its coefficients can be computed on demands::
sage: exp = phi.exponential(); exp
z + ((1/(T^2+T))*z^2) + ((1/(T^8+T^6+T^5+T^3))*z^4) + O(z^8)
sage: exp[2^4]
1/(T^64 + T^56 + T^52 + ... + T^27 + T^23 + T^15)
sage: exp[2^5]
1/(T^160 + T^144 + T^136 + ... + T^55 + T^47 + T^31)
On the contrary, when ``prec`` is a finite number, all the
required coefficients are computed at once::
sage: phi.exponential(prec=10)
z + (1/(T^2 + T))*z^2 + (1/(T^8 + T^6 + T^5 + T^3))*z^4 + (1/(T^24 + T^20 + T^18 + T^17 + T^14 + T^13 + T^11 + T^7))*z^8 + O(z^10)
Example in higher rank::
sage: A = GF(5)['T']
Expand Down Expand Up @@ -216,7 +227,6 @@ def exponential(self, name='z'):
See section 4.6 of [Gos1998]_ for the definition of the
exponential.
"""
L = LazyPowerSeriesRing(self._base, name)
zero = self._base.zero()
q = self._Fq.cardinality()

Expand All @@ -228,7 +238,13 @@ def coeff_exp(k):
return self._compute_coefficient_exp(v)
else:
return zero
return L(coeff_exp, valuation=1)

if prec is Infinity:
L = LazyPowerSeriesRing(self._base, name)
return L(coeff_exp, valuation=1)
else:
L = PowerSeriesRing(self._base, name, default_prec=prec)
return L([0] + [coeff_exp(i) for i in range(1,prec)], prec=prec)

@cached_method
def _compute_coefficient_log(self, k):
Expand Down Expand Up @@ -264,7 +280,7 @@ def _compute_coefficient_log(self, k):
c += self._compute_coefficient_log(i)*self._gen[j]**(q**i)
return c/(T - T**(q**k))

def logarithm(self, name='z'):
def logarithm(self, prec=Infinity, name='z'):
r"""
Return the logarithm of the given Drinfeld module.
Expand All @@ -275,27 +291,36 @@ def logarithm(self, name='z'):
INPUT:
- ``prec`` -- an integer or ``Infinity`` (default: ``Infinity``);
the precision at which the series is returned; if ``Infinity``,
a lazy power series in returned
- ``name`` -- string (default: ``'z'``); the name of the
generator of the lazy power series ring
OUTPUT: a lazy power series over the base field
EXAMPLES::
sage: A = GF(2)['T']
sage: K.<T> = Frac(A)
sage: phi = DrinfeldModule(A, [T, 1])
sage: log = phi.logarithm(); log
z + ((1/(T^2+T))*z^2) + ((1/(T^6+T^5+T^3+T^2))*z^4) + O(z^8)
The logarithm is returned as a lazy power series, meaning that
any of its coefficients can be computed on demands::
When ``prec`` is ``Infinity`` (which is the default),
the logarithm is returned as a lazy power series, meaning
that any of its coefficients can be computed on demands::
sage: log = phi.logarithm(); log
z + ((1/(T^2+T))*z^2) + ((1/(T^6+T^5+T^3+T^2))*z^4) + O(z^8)
sage: log[2^4]
1/(T^30 + T^29 + T^27 + ... + T^7 + T^5 + T^4)
sage: log[2^5]
1/(T^62 + T^61 + T^59 + ... + T^8 + T^6 + T^5)
On the contrary, when ``prec`` is a finite number, all the
required coefficients are computed at once::
sage: phi.logarithm(prec=10)
z + (1/(T^2 + T))*z^2 + (1/(T^6 + T^5 + T^3 + T^2))*z^4 + (1/(T^14 + T^13 + T^11 + T^10 + T^7 + T^6 + T^4 + T^3))*z^8 + O(z^10)
Example in higher rank::
sage: A = GF(5)['T']
Expand All @@ -317,7 +342,6 @@ def logarithm(self, name='z'):
sage: log[2**3] == -1/((T**q - T)*(T**(q**2) - T)*(T**(q**3) - T)) # expected value
True
"""
L = LazyPowerSeriesRing(self._base, name)
q = self._Fq.cardinality()

def coeff_log(k):
Expand All @@ -328,7 +352,13 @@ def coeff_log(k):
return self._compute_coefficient_log(v)
else:
return self._base.zero()
return L(coeff_log, valuation=1)

if prec is Infinity:
L = LazyPowerSeriesRing(self._base, name)
return L(coeff_log, valuation=1)
else:
L = PowerSeriesRing(self._base, name, default_prec=prec)
return L([0] + [coeff_log(i) for i in range(1, prec)], prec=prec)

@cached_method
def _compute_goss_polynomial(self, n, q, poly_ring, X):
Expand Down

0 comments on commit 5f6e2d5

Please sign in to comment.