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

Commit

Permalink
Trac #18416: global precision
Browse files Browse the repository at this point in the history
  • Loading branch information
mjungmath committed Jan 20, 2021
1 parent 13b4090 commit d4b84d0
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 43 deletions.
4 changes: 2 additions & 2 deletions src/sage/misc/defaults.py
Expand Up @@ -96,7 +96,7 @@ def set_default_variable_name(name, separator=''):


# default series precision
series_prec = 20
series_prec = 15


def series_precision():
Expand All @@ -107,7 +107,7 @@ def series_precision():
EXAMPLES::
sage: series_precision()
20
15
"""
return series_prec

Expand Down
3 changes: 3 additions & 0 deletions src/sage/rings/laurent_series_ring.py
Expand Up @@ -269,6 +269,7 @@ def base_extend(self, R):
sage: K.<x> = LaurentSeriesRing(QQ, default_prec=4)
sage: K.base_extend(QQ['t'])
Laurent Series Ring in x over Univariate Polynomial Ring in t over Rational Field
"""
if R.has_coerce_map_from(self.base_ring()):
return self.change_ring(R)
Expand Down Expand Up @@ -316,6 +317,7 @@ def change_ring(self, R):
Laurent Series Ring in x over Integer Ring
sage: R.default_prec()
4
"""
return LaurentSeriesRing(R, self.variable_names(),
default_prec=self.default_prec(),
Expand Down Expand Up @@ -709,6 +711,7 @@ def default_prec(self):
sage: R.<x> = LaurentSeriesRing(QQ, default_prec=5)
sage: R.default_prec()
5
"""
return self._power_series_ring.default_prec()

Expand Down
73 changes: 59 additions & 14 deletions src/sage/rings/multi_power_series_ring.py
Expand Up @@ -213,7 +213,6 @@

from sage.rings.infinity import infinity
import sage.misc.latex as latex
from sage.structure.nonexact import Nonexact

from sage.rings.multi_power_series_ring_element import MPowerSeries
from sage.categories.commutative_rings import CommutativeRings
Expand Down Expand Up @@ -245,7 +244,7 @@ def is_MPowerSeriesRing(x):
return isinstance(x, MPowerSeriesRing_generic)


class MPowerSeriesRing_generic(PowerSeriesRing_generic, Nonexact):
class MPowerSeriesRing_generic(PowerSeriesRing_generic):
r"""
A multivariate power series ring. This class is implemented as a
single variable power series ring in the variable ``T`` over a
Expand Down Expand Up @@ -283,7 +282,7 @@ class MPowerSeriesRing_generic(PowerSeriesRing_generic, Nonexact):
Element = MPowerSeries
@staticmethod
def __classcall__(cls, base_ring, num_gens, name_list,
order='negdeglex', default_prec=10, sparse=False):
order='negdeglex', sparse=False):
"""
Preprocessing of arguments: The term order can be given as string
or as a :class:`~sage.rings.polynomial.term_order.TermOrder` instance.
Expand All @@ -298,10 +297,10 @@ def __classcall__(cls, base_ring, num_gens, name_list,
"""
order = TermOrder(order,num_gens)
return super(MPowerSeriesRing_generic,cls).__classcall__(cls, base_ring, num_gens, name_list,
order, default_prec, sparse)
order, sparse)

def __init__(self, base_ring, num_gens, name_list,
order='negdeglex', default_prec=10, sparse=False):
order='negdeglex', sparse=False):
"""
Initializes a multivariate power series ring. See PowerSeriesRing
for complete documentation.
Expand All @@ -321,9 +320,6 @@ def __init__(self, base_ring, num_gens, name_list,
- ``order`` -- ordering of variables; default is
negative degree lexicographic
- ``default_prec`` -- The default total-degree precision for
elements. The default value of default_prec is 10.
- ``sparse`` -- whether or not the power series are sparse.
The underlying polynomial ring is always sparse.
Expand Down Expand Up @@ -368,20 +364,19 @@ def __init__(self, base_ring, num_gens, name_list,
CommutativeRing.__init__(self, base_ring, name_list, category =
_IntegralDomains if base_ring in
_IntegralDomains else _CommutativeRings)
Nonexact.__init__(self, default_prec)

# underlying polynomial ring in which to represent elements
self._poly_ring_ = PolynomialRing(base_ring, self.variable_names(), order=order)
# because sometimes PowerSeriesRing_generic calls self.__poly_ring
self._PowerSeriesRing_generic__poly_ring = self._poly_ring()

# background univariate power series ring
self._bg_power_series_ring = PowerSeriesRing(self._poly_ring_, 'Tbg', sparse=sparse, default_prec=default_prec)
self._bg_power_series_ring = PowerSeriesRing(self._poly_ring_, 'Tbg', sparse=sparse)
self._bg_indeterminate = self._bg_power_series_ring.gen()

self._is_sparse = sparse
self._params = (base_ring, num_gens, name_list,
order, default_prec, sparse)
order, sparse)
self._populate_coercion_lists_()

def _repr_(self):
Expand Down Expand Up @@ -493,9 +488,8 @@ def construction(self):
EXAMPLES::
sage: M = PowerSeriesRing(QQ,4,'f'); M
sage: M = PowerSeriesRing(QQ, 4, 'f'); M
Multivariate Power Series Ring in f0, f1, f2, f3 over Rational Field
sage: (c,R) = M.construction(); (c,R)
(Completion[('f0', 'f1', 'f2', 'f3'), prec=12],
Multivariate Polynomial Ring in f0, f1, f2, f3 over Rational Field)
Expand Down Expand Up @@ -561,9 +555,60 @@ def change_ring(self, R):
sage: S.change_ring(GF(5))
Multivariate Power Series Ring in x, y over Finite Field of size 5
"""
return PowerSeriesRing(R, names = self.variable_names(), default_prec = self.default_prec())
return PowerSeriesRing(R, names = self.variable_names())

def default_prec(self):
r"""
Return default precision for series.
EXAMPLES::
sage: R.<x, y> = PowerSeriesRing(ZZ, default_prec=10)
sage: R.default_prec()
10
sage: set_series_precision(12)
sage: R.default_prec()
12
"""
from sage.misc.defaults import series_precision
return series_precision()

def set_default_prec(self, prec):
r"""
Set default precision for series.
EXAMPLES:
sage: R.<x, y> = PowerSeriesRing(ZZ, default_prec=12)
sage: R.default_prec()
12
sage: R.set_default_prec(5)
sage: R.default_prec()
5
.. WARNING::
The method ``set_default_prec`` is linked to
``set_series_precision`` and therefore changes the global
precision for multivariate series as well.
Setting the precision there, changes the precision globally, too::
sage: series_precision()
5
Consequently, the precision can also be changed with
``set_series_precision``::
sage: set_series_precision(12)
sage: R.default_prec()
12
sage: set_series_precision(20) # reset to default
"""
from sage.misc.defaults import set_series_precision
set_series_precision(prec)

def remove_var(self, *var):
"""
Expand Down
106 changes: 81 additions & 25 deletions src/sage/rings/power_series_ring.py
Expand Up @@ -136,7 +136,6 @@
from . import ring
from .infinity import infinity
import sage.misc.latex as latex
from sage.structure.nonexact import Nonexact

from sage.interfaces.magma import MagmaElement
from sage.rings.fraction_field_element import FractionFieldElement
Expand Down Expand Up @@ -384,7 +383,7 @@ def PowerSeriesRing(base_ring, name=None, arg2=None, names=None,
if name is None:
raise TypeError("You must specify the name of the indeterminate of the Power series ring.")

key = (base_ring, name, default_prec, sparse, implementation)
key = (base_ring, name, sparse, implementation)
if PowerSeriesRing_generic.__classcall__.is_in_cache(key):
return PowerSeriesRing_generic(*key)

Expand All @@ -395,15 +394,23 @@ def PowerSeriesRing(base_ring, name=None, arg2=None, names=None,
if not (name is None or isinstance(name, str)):
raise TypeError("variable name must be a string or None")

# handle default precision
if default_prec is not None:
if default_prec < 0:
raise ValueError("default_prec (= {}) must be non-negative".format(default_prec))
else:
from sage.misc.defaults import set_series_precision
set_series_precision(default_prec)

if base_ring in _Fields:
R = PowerSeriesRing_over_field(base_ring, name, default_prec,
sparse=sparse, implementation=implementation)
R = PowerSeriesRing_over_field(base_ring, name, sparse=sparse,
implementation=implementation)
elif base_ring in _IntegralDomains:
R = PowerSeriesRing_domain(base_ring, name, default_prec,
sparse=sparse, implementation=implementation)
R = PowerSeriesRing_domain(base_ring, name, sparse=sparse,
implementation=implementation)
elif base_ring in _CommutativeRings:
R = PowerSeriesRing_generic(base_ring, name, default_prec,
sparse=sparse, implementation=implementation)
R = PowerSeriesRing_generic(base_ring, name, sparse=sparse,
implementation=implementation)
else:
raise TypeError("base_ring must be a commutative ring")
return R
Expand All @@ -425,14 +432,19 @@ def _multi_variate(base_ring, num_gens=None, names=None,
raise TypeError("variable names must be a string, tuple or list")
names = normalize_names(num_gens, names)
num_gens = len(names)
if default_prec is None:
default_prec = 12
# handle default precision
if default_prec is not None:
if default_prec < 0:
raise ValueError("default_prec (= {}) must be non-negative".format(default_prec))
else:
from sage.misc.defaults import set_series_precision
set_series_precision(default_prec)

if base_ring not in commutative_rings.CommutativeRings():
raise TypeError("base_ring must be a commutative ring")
from sage.rings.multi_power_series_ring import MPowerSeriesRing_generic
R = MPowerSeriesRing_generic(base_ring, num_gens, names,
order=order, default_prec=default_prec, sparse=sparse)
R = MPowerSeriesRing_generic(base_ring, num_gens, names, order=order,
sparse=sparse)
return R


Expand All @@ -458,12 +470,12 @@ def is_PowerSeriesRing(R):
else:
return False

class PowerSeriesRing_generic(UniqueRepresentation, ring.CommutativeRing, Nonexact):
class PowerSeriesRing_generic(UniqueRepresentation, ring.CommutativeRing):
"""
A power series ring.
"""

def __init__(self, base_ring, name=None, default_prec=None, sparse=False,
def __init__(self, base_ring, name=None, sparse=False,
implementation=None, category=None):
"""
Initializes a power series ring.
Expand All @@ -475,8 +487,6 @@ def __init__(self, base_ring, name=None, default_prec=None, sparse=False,
- ``name`` - name of the indeterminate
- ``default_prec`` - the default precision
- ``sparse`` - whether or not power series are
sparse
Expand Down Expand Up @@ -541,12 +551,6 @@ def __init__(self, base_ring, name=None, default_prec=None, sparse=False,

self.__poly_ring = R
self.__is_sparse = sparse
if default_prec is None:
from sage.misc.defaults import series_precision
default_prec = series_precision()
elif default_prec < 0:
raise ValueError("default_prec (= %s) must be non-negative"
% default_prec)

if implementation == 'poly':
self.Element = power_series_poly.PowerSeries_poly
Expand All @@ -564,7 +568,6 @@ def __init__(self, base_ring, name=None, default_prec=None, sparse=False,
ring.CommutativeRing.__init__(self, base_ring, names=name,
category=getattr(self, '_default_category',
_CommutativeRings))
Nonexact.__init__(self, default_prec)
if self.Element is PowerSeries_pari:
self.__generator = self.element_class(self, R.gen().__pari__())
else:
Expand Down Expand Up @@ -810,6 +813,58 @@ def _element_constructor_(self, f, prec=infinity, check=True):
raise TypeError("Can only convert series into ring with same variable name.")
return self.element_class(self, f, prec, check=check)

def default_prec(self):
r"""
Return default precision for series.
EXAMPLES::
sage: R.<x> = PowerSeriesRing(ZZ)
sage: R.default_prec()
20
sage: set_series_precision(15)
sage: R.default_prec()
15
"""
from sage.misc.defaults import series_precision
return series_precision()

def set_default_prec(self, prec):
r"""
Set default precision for series.
EXAMPLES:
sage: R.<x> = PowerSeriesRing(ZZ, default_prec=10)
sage: R.default_prec()
10
sage: R.set_default_prec(5)
sage: R.default_prec()
5
.. WARNING::
The method ``set_default_prec`` is linked to
``set_series_precision`` and therefore changes the global series
precision as well.
Setting the precision there, changes the precision globally, too::
sage: series_precision()
5
Consequently, the precision can also be changed with
``set_series_precision``::
sage: set_series_precision(20)
sage: R.default_prec()
20
"""
from sage.misc.defaults import set_series_precision
set_series_precision(prec)

def construction(self):
"""
Return the functorial construction of self, namely, completion of
Expand Down Expand Up @@ -999,7 +1054,7 @@ def change_ring(self, R):
sage: R.base_extend(QuadraticField(3,'a'))
Power Series Ring in T over Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878?
"""
return PowerSeriesRing(R, name = self.variable_name(), default_prec = self.default_prec())
return PowerSeriesRing(R, name = self.variable_name())

def change_var(self, var):
"""
Expand Down Expand Up @@ -1245,12 +1300,13 @@ def laurent_series_ring(self):
5
sage: f = 1+t; g=1/f; g
1 - t + t^2 - t^3 + t^4 + O(t^5)
"""
try:
return self.__laurent_series_ring
except AttributeError:
self.__laurent_series_ring = laurent_series_ring.LaurentSeriesRing(
self.base_ring(), self.variable_name(), default_prec=self.default_prec(), sparse=self.is_sparse())
self.base_ring(), self.variable_name(), sparse=self.is_sparse())
return self.__laurent_series_ring

class PowerSeriesRing_domain(PowerSeriesRing_generic, ring.IntegralDomain):
Expand Down

0 comments on commit d4b84d0

Please sign in to comment.