summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRelease Manager <release@sagemath.org>2018-03-07 00:24:21 +0100
committerVolker Braun <vbraun.name@gmail.com>2018-03-07 00:24:21 +0100
commit30d778252cb5774929460c6a62de8b18e5714384 (patch)
tree5338bea158194cadd7ea3d80e4f307313e30531c
parentTrac #21524: configure.ac: write build/make/Makefile within an AC_CONFIG_FILE... (diff)
parentFix doctest (diff)
Trac #23505: Lattice precision for p-adics
In several recent papers, David Roe, Tristan Vaccon and I explain that lattices allow a sharp track of precision: if f is a function we want to evaluate and x is an input given with some uncertainty modeled by a lattice H, then the uncertainty on the output f(x) is exactly df_x(H). For much more details, I refer to my lecture notes http://xavier.toonywood.org/papers/publis/course-padic.pdf The aim of this ticket is to propose a rough implementation of these ideas. You can play with the latest version of this by clicking on launch binder [https://github.com/saraedum/sage-binder-env/tree/t-23505 -lattice-precision here]. Below is a small demo (extracted from the doctest). {{{ Below is a small demo of the features by this model of precision: sage: R = ZpLP(3, print_mode='terse') sage: x = R(1,10) Of course, when we multiply by 3, we gain one digit of absolute precision: sage: 3*x 3 + O(3^11) The lattice precision machinery sees this even if we decompose the computation into several steps: sage: y = x+x sage: y 2 + O(3^10) sage: x + y 3 + O(3^11) The same works for the multiplication: sage: z = x^2 sage: z 1 + O(3^10) sage: x*z 1 + O(3^11) This comes more funny when we are working with elements given at different precisions: sage: R = ZpLP(2, print_mode='terse') sage: x = R(1,10) sage: y = R(1,5) sage: z = x+y; z 2 + O(2^5) sage: t = x-y; t 0 + O(2^5) sage: z+t # observe that z+t = 2*x 2 + O(2^11) sage: z-t # observe that z-t = 2*y 2 + O(2^6) sage: x = R(28888,15) sage: y = R(204,10) sage: z = x/y; z 242 + O(2^9) sage: z*y # which is x 28888 + O(2^15) The SOMOS sequence is the sequence defined by the recurrence: ..MATH:: u_n = rac {u_{n-1} u_{n-3} + u_{n-2}^2} {u_{n-4}} It is known for its numerical instability. On the one hand, one can show that if the initial values are invertible in mathbb{Z}_p and known at precision O(p^N) then all the next terms of the SOMOS sequence will be known at the same precision as well. On the other hand, because of the division, when we unroll the recurrence, we loose a lot of precision. Observe: sage: R = Zp(2, 30, print_mode='terse') sage: a,b,c,d = R(1,15), R(1,15), R(1,15), R(3,15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 4 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 13 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 55 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 21975 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 6639 + O(2^13) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 7186 + O(2^13) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 569 + O(2^13) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 253 + O(2^13) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 4149 + O(2^13) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 2899 + O(2^12) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 3072 + O(2^12) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 349 + O(2^12) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 619 + O(2^12) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 243 + O(2^12) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 3 + O(2^2) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 2 + O(2^2) If instead, we use the lattice precision, everything goes well: sage: R = ZpLP(2, 30, print_mode='terse') sage: a,b,c,d = R(1,15), R(1,15), R(1,15), R(3,15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 4 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 13 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 55 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 21975 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 23023 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 31762 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 16953 + O(2^15) sage: a,b,c,d = b,c,d,(b*d+c*c)/a; print d 16637 + O(2^15) sage: for _ in range(100): ....: a,b,c,d = b,c,d,(b*d+c*c)/a sage: a 15519 + O(2^15) sage: b 32042 + O(2^15) sage: c 17769 + O(2^15) sage: d 20949 + O(2^15) BEHIND THE SCENE: The precision is global. It is encoded by a lattice in a huge vector space whose dimension is the number of elements having this parent. Concretely, this precision datum is an instance of the class "sage.rings.padic.lattice_precision.PrecisionLattice". It is attached to the parent and is created at the same time as the parent. (It is actually a bit more subtle because two different parents may share the same instance; this happens for instance for a p-adic ring and its field of fractions.) This precision datum is accessible through the method "precision()": sage: R = ZpLP(5, print_mode='terse') sage: prec = R.precision() sage: prec Precision Lattice on 0 object This instance knows about all elements of the parent, it is automatically updated when a new element (of this parent) is created: sage: x = R(3513,10) sage: prec Precision Lattice on 1 object sage: y = R(176,5) sage: prec Precision Lattice on 2 objects sage: z = R.random_element() sage: prec Precision Lattice on 3 objects The method "tracked_elements()" provides the list of all tracked elements: sage: prec.tracked_elements() [3513 + O(5^10), 176 + O(5^5), ...] Similarly, when a variable is collected by the garbage collector, the precision lattice is updated. Note however that the update might be delayed. We can force it with the method "del_elements()": sage: z = 0 sage: prec Precision Lattice on 3 objects sage: prec.del_elements() sage: prec Precision Lattice on 2 objects The method "precision_lattice()" returns (a matrix defining) the lattice that models the precision. Here we have: sage: prec.precision_lattice() [9765625 0] [ 0 3125] Observe that 5^10 = 9765625 and 5^5 = 3125. The above matrix then reflects the precision on x and y. Now, observe how the precision lattice changes while performing computations: sage: x, y = 3*x+2*y, 2*(x-y) sage: prec.del_elements() sage: prec.precision_lattice() [ 3125 48825000] [ 0 48828125] The matrix we get is no longer diagonal, meaning that some digits of precision are diffused among the two new elements x and y. They nevertheless show up when we compute for instance x+y: sage: x 1516 + O(5^5) sage: y 424 + O(5^5) sage: x+y 17565 + O(5^11) It is these diffused digits of precision (which are tracked but do not appear on the printing) that allow to be always sharp on precision. PERFORMANCES: Each elementary operation requires significant manipulations on the lattice precision and then is costly. Precisely: * The creation of a new element has a cost O(n) when n is the number of tracked elements. * The destruction of one element has a cost O(m^2) when m is the distance between the destroyed element and the last one. Fortunately, it seems that m tends to be small in general (the dynamics of the list of tracked elements is rather close to that of a stack). It is nevertheless still possible to manipulate several hundred variables (e.g. squares matrices of size 5 or polynomials of degree 20 are accessible). The class "PrecisionLattice" provides several features for introspection (especially concerning timings). If enables, it maintains an history of all actions and stores the wall time of each of them: sage: R = ZpLP(3) sage: prec = R.precision() sage: prec.history_enable() sage: M = random_matrix(R, 5) sage: d = M.determinant() sage: print prec.history() # somewhat random --- 0.004212s oooooooooooooooooooooooooooooooooooo 0.000003s oooooooooooooooooooooooooooooooooo~~ 0.000010s oooooooooooooooooooooooooooooooooo 0.001560s ooooooooooooooooooooooooooooooooooooooooo 0.000004s ooooooooooooooooooooooooooooo~oooo~oooo~o 0.002168s oooooooooooooooooooooooooooooooooooooo 0.001787s ooooooooooooooooooooooooooooooooooooooooo 0.000004s oooooooooooooooooooooooooooooooooooooo~~o 0.000198s ooooooooooooooooooooooooooooooooooooooo 0.001152s ooooooooooooooooooooooooooooooooooooooooo 0.000005s ooooooooooooooooooooooooooooooooo~oooo~~o 0.000853s oooooooooooooooooooooooooooooooooooooo 0.000610s ooooooooooooooooooooooooooooooooooooooo ... 0.003879s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000006s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~~ 0.000036s oooooooooooooooooooooooooooooooooooooooooooooooooooo 0.006737s oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000005s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~~ooooo 0.002637s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.007118s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000008s oooooooooooooooooooooooooooooooooooooooooooooooooooo~~~~o~~~~oooo 0.003504s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.005371s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000006s ooooooooooooooooooooooooooooooooooooooooooooooooooooo~~~o~~~ooo 0.001858s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.003584s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000004s oooooooooooooooooooooooooooooooooooooooooooooooooooooo~~o~~oo 0.000801s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.001916s ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo 0.000022s ooooooooooooooooooooooooooooo~~~~~~~~~~~~~~~~~~~~~~oooo~o~o 0.014705s ooooooooooooooooooooooooooooooooooo 0.001292s ooooooooooooooooooooooooooooooooooooo 0.000002s ooooooooooooooooooooooooooooooooooo~o The symbol o symbolized a tracked element. The symbol ~ means that the element is marked for deletion. The global timings are also accessible as follows: sage: prec.timings() # somewhat random {'add': 0.25049376487731934, 'del': 0.11911273002624512, 'mark': 0.0004909038543701172, 'partial reduce': 0.0917658805847168} }}} URL: https://trac.sagemath.org/23505 Reported by: caruso Ticket author(s): Xavier Caruso Reviewer(s): David Roe, Julian RĂ¼th
-rw-r--r--src/doc/en/reference/references/index.rst7
-rw-r--r--src/sage/categories/pushout.py7
-rw-r--r--src/sage/rings/padics/all.py4
-rw-r--r--src/sage/rings/padics/factory.py651
-rw-r--r--src/sage/rings/padics/generic_nodes.py465
-rw-r--r--src/sage/rings/padics/lattice_precision.py2835
-rw-r--r--src/sage/rings/padics/local_generic.py79
-rw-r--r--src/sage/rings/padics/local_generic_element.pyx6
-rw-r--r--src/sage/rings/padics/misc.py4
-rw-r--r--src/sage/rings/padics/padic_base_generic.py40
-rw-r--r--src/sage/rings/padics/padic_base_leaves.py274
-rw-r--r--src/sage/rings/padics/padic_generic.py50
-rw-r--r--src/sage/rings/padics/padic_lattice_element.py1311
-rw-r--r--src/sage/rings/padics/padic_printing.pyx7
14 files changed, 5581 insertions, 159 deletions
diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst
index a78c2ae..4a9098b 100644
--- a/src/doc/en/reference/references/index.rst
+++ b/src/doc/en/reference/references/index.rst
@@ -673,6 +673,13 @@ REFERENCES:
.. [Crossproduct] Algebraic Properties of the Cross Product
:wikipedia:`Cross_product`
+.. [CRV2018] Xavier Caruso, David Roe and Tristan Vaccon.
+ *ZpL: a p-adic precision package*, (2018) :arxiv:`1802.08532`.
+
+.. [CRV2014] Xavier Caruso, David Roe and Tristan Vaccon.
+ *Tracking p-adic precision*,
+ LMS J. Comput. Math. **17** (2014), 274-294.
+
.. [CS1986] \J. Conway and N. Sloane. *Lexicographic codes:
error-correcting codes from game theory*, IEEE
Trans. Infor. Theory **32** (1986) 337-348.
diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py
index 602117f..bccd0b5 100644
--- a/src/sage/categories/pushout.py
+++ b/src/sage/categories/pushout.py
@@ -2318,7 +2318,7 @@ class CompletionFunctor(ConstructionFunctor):
"""
rank = 4
_real_types = ['Interval', 'Ball', 'MPFR', 'RDF', 'RLF', 'RR']
- _dvr_types = [None, 'fixed-mod','floating-point','capped-abs','capped-rel','lazy']
+ _dvr_types = [None, 'fixed-mod', 'floating-point', 'capped-abs', 'capped-rel', 'lattice-cap', 'lattice-float']
def __init__(self, p, prec, extras=None):
"""
@@ -2329,14 +2329,15 @@ class CompletionFunctor(ConstructionFunctor):
- ``prec``: an integer, yielding the precision in bits. Note that
if ``p`` is prime then the ``prec`` is the *capped* precision,
while it is the *set* precision if ``p`` is ``+Infinity``.
+ In the ``lattice-cap`` precision case, ``prec`` will be a tuple instead.
- ``extras`` (optional dictionary): Information on how to print elements, etc.
If 'type' is given as a key, the corresponding value should be a string among the following:
- 'RDF', 'Interval', 'RLF', or 'RR' for completions at infinity
- - 'capped-rel', 'capped-abs', 'fixed-mod' or 'lazy' for completions at a finite place
- or ideal of a DVR.
+ - 'capped-rel', 'capped-abs', 'fixed-mod', 'lattice-cap' or 'lattice-float'
+ for completions at a finite place or ideal of a DVR.
TESTS::
diff --git a/src/sage/rings/padics/all.py b/src/sage/rings/padics/all.py
index 3e361a9..0c6d31d 100644
--- a/src/sage/rings/padics/all.py
+++ b/src/sage/rings/padics/all.py
@@ -1,7 +1,7 @@
from __future__ import absolute_import
from .generic_nodes import is_pAdicField, is_pAdicRing
-from .factory import Zp, Zq, Zp as pAdicRing, ZpCR, ZpCA, ZpFM, ZpFP, ZqCR, ZqCA, ZqFM, ZqFP #, ZpL, ZqL
-from .factory import Qp, Qq, Qp as pAdicField, QpCR, QpFP, QqCR, QqFP #, QpL, QqL
+from .factory import Zp, Zq, Zp as pAdicRing, ZpCR, ZpCA, ZpFM, ZpFP, ZpLC, ZpLF, ZqCR, ZqCA, ZqFM, ZqFP #, ZpL, ZqL
+from .factory import Qp, Qq, Qp as pAdicField, QpCR, QpFP, QpLC, QpLF, QqCR, QqFP #, QpL, QqL
from .factory import pAdicExtension
from .padic_generic import local_print_mode
from .pow_computer import PowComputer
diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py
index 291172c..d3916b7 100644
--- a/src/sage/rings/padics/factory.py
+++ b/src/sage/rings/padics/factory.py
@@ -1,4 +1,4 @@
-"""
+r"""
Factory
This file contains the constructor classes and functions for `p`-adic rings and fields.
@@ -6,6 +6,15 @@ This file contains the constructor classes and functions for `p`-adic rings and
AUTHORS:
- David Roe
+
+TESTS::
+
+ sage: R = ZpLC(2)
+ doctest:...: FutureWarning: This class/method/function is marked as experimental. It, its functionality or its interface might change without a formal deprecation.
+ See http://trac.sagemath.org/23505 for details.
+ sage: R = ZpLF(2)
+ sage: R = QpLC(2)
+ sage: R = QpLF(2)
"""
#*****************************************************************************
@@ -20,8 +29,11 @@ AUTHORS:
#*****************************************************************************
from __future__ import absolute_import, print_function
+from sage.misc.superseded import experimental
+
from sage.structure.factory import UniqueFactory
from sage.rings.integer import Integer
+from sage.rings.infinity import Infinity
from sage.structure.factorization import Factorization
from sage.rings.integer_ring import ZZ
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
@@ -31,8 +43,10 @@ from .padic_base_leaves import (pAdicRingCappedRelative,
pAdicRingCappedAbsolute,
pAdicRingFixedMod,
pAdicRingFloatingPoint,
+ pAdicRingLattice,
pAdicFieldCappedRelative,
- pAdicFieldFloatingPoint)
+ pAdicFieldFloatingPoint,
+ pAdicFieldLattice)
from . import padic_printing
######################################################
@@ -47,35 +61,30 @@ from functools import reduce
ext_table = {}
ext_table['e', pAdicFieldCappedRelative] = EisensteinExtensionFieldCappedRelative
-#ext_table['e', pAdicFieldLazy] = EisensteinExtensionFieldLazy
ext_table['e', pAdicRingCappedAbsolute] = EisensteinExtensionRingCappedAbsolute
ext_table['e', pAdicRingCappedRelative] = EisensteinExtensionRingCappedRelative
ext_table['e', pAdicRingFixedMod] = EisensteinExtensionRingFixedMod
#ext_table['e', pAdicRingFloatingPoint] = EisensteinExtensionRingFloatingPoint
#ext_table['e', pAdicFieldFloatingPoint] = EisensteinExtensionFieldFloatingPoint
-#ext_table['e', pAdicRingLazy] = EisensteinExtensionRingLazy
#ext_table['p', pAdicFieldCappedRelative] = pAdicGeneralExtensionFieldCappedRelative
-#ext_table['p', pAdicFieldLazy] = pAdicGeneralExtensionFieldLazy
#ext_table['p', pAdicRingCappedAbsolute] = pAdicGeneralExtensionRingCappedAbsolute
#ext_table['p', pAdicRingCappedRelative] = pAdicGeneralExtensionRingCappedRelative
#ext_table['p', pAdicRingFixedMod] = pAdicGeneralExtensionRingFixedMod
-#ext_table['p', pAdicRingLazy] = pAdicGeneralExtensionRingLazy
ext_table['u', pAdicFieldCappedRelative] = UnramifiedExtensionFieldCappedRelative
-#ext_table['u', pAdicFieldLazy] = UnramifiedExtensionFieldLazy
ext_table['u', pAdicRingCappedAbsolute] = UnramifiedExtensionRingCappedAbsolute
ext_table['u', pAdicRingCappedRelative] = UnramifiedExtensionRingCappedRelative
ext_table['u', pAdicRingFixedMod] = UnramifiedExtensionRingFixedMod
ext_table['u', pAdicRingFloatingPoint] = UnramifiedExtensionRingFloatingPoint
ext_table['u', pAdicFieldFloatingPoint] = UnramifiedExtensionFieldFloatingPoint
-#ext_table['u', pAdicRingLazy] = UnramifiedExtensionRingLazy
def _default_show_prec(type, print_mode):
- """
+ r"""
Returns the default show_prec value for a given type and printing mode.
INPUT:
- - ``type`` -- a string: ``'capped-rel'``, ``'capped-abs'``, ``'fixed-mod'`` or ``'floating-point'``
+ - ``type`` -- a string: ``'capped-rel'``, ``'capped-abs'``, ``'fixed-mod'``, ``'floating-point'``,
+ ``'lattice-cap'`` or ``'lattice-float'``
- ``print_mode`` -- a string: ``'series'``, ``'terse'``, ``'val-unit'``, ``'digits'``, ``'bars'``
EXAMPLES::
@@ -95,8 +104,8 @@ def _default_show_prec(type, print_mode):
else:
return False
-def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_sep, print_alphabet, print_max_terms, show_prec, check, valid_non_lazy_types):
- """
+def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_sep, print_alphabet, print_max_terms, show_prec, check, valid_types, label=None):
+ r"""
This implements create_key for Zp and Qp: moving it here prevents code duplication.
It fills in unspecified values and checks for contradictions in the input. It also standardizes irrelevant options so that duplicate parents are not created.
@@ -105,19 +114,61 @@ def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_se
sage: from sage.rings.padics.factory import get_key_base
sage: get_key_base(11, 5, 'capped-rel', None, None, None, None, ':', None, None, False, True, ['capped-rel'])
- (11, 5, 'capped-rel', 'series', '11', True, '|', (), -1, False)
+ (11, 5, 'capped-rel', 'series', '11', True, '|', (), -1, False, None)
sage: get_key_base(12, 5, 'capped-rel', 'digits', None, None, None, None, None, None, True, False, ['capped-rel'])
- (12, 5, 'capped-rel', 'digits', '12', True, '|', ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B'), -1, True)
+ (12,
+ 5,
+ 'capped-rel',
+ 'digits',
+ '12',
+ True,
+ '|',
+ ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B'),
+ -1,
+ True,
+ None)
"""
- if prec is None:
- prec = DEFAULT_PREC
if check:
if not isinstance(p, Integer):
p = Integer(p)
- if not isinstance(prec, Integer):
- prec = Integer(prec)
if not p.is_prime():
raise ValueError("p must be prime")
+ if type == 'lattice-cap':
+ relative_cap = absolute_cap = None
+ if prec is not None:
+ try:
+ relative_cap, absolute_cap = prec
+ except (ValueError, TypeError):
+ relative_cap = prec
+ if relative_cap is not None:
+ if relative_cap is not Infinity:
+ try:
+ relative_cap = Integer(relative_cap)
+ except TypeError:
+ raise TypeError("relative cap must be either a positive integer or infinity")
+ if relative_cap <= 0:
+ raise ValueError("relative cap must be positive")
+ if absolute_cap is not None:
+ try:
+ absolute_cap = Integer(absolute_cap)
+ except TypeError:
+ raise TypeError("absolute cap must be an integer")
+ if relative_cap is None and absolute_cap is None:
+ relative_cap = DEFAULT_PREC
+ absolute_cap = 2 * DEFAULT_PREC
+ elif relative_cap is None:
+ relative_cap = Infinity
+ elif absolute_cap is None:
+ absolute_cap = 2 * relative_cap
+ prec = (relative_cap, absolute_cap)
+ else:
+ if prec is not None:
+ prec = Integer(prec)
+ if prec is None:
+ if type == 'lattice-cap':
+ prec = (DEFAULT_PREC, 2*DEFAULT_PREC)
+ else:
+ prec = DEFAULT_PREC
print_ram_name = ram_name
if isinstance(print_mode, dict):
if 'pos' in print_mode:
@@ -185,11 +236,10 @@ def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_se
name = str(names)
if show_prec is None:
show_prec = _default_show_prec(type, print_mode)
- if type in valid_non_lazy_types:
- key = (p, prec, type, print_mode, name, print_pos, print_sep, tuple(print_alphabet), print_max_terms, show_prec)
+ if type in valid_types:
+ key = (p, prec, type, print_mode, name, print_pos, print_sep, tuple(print_alphabet), print_max_terms, show_prec, label)
else:
- print(type)
- raise ValueError("type must be %s"%(", ".join(valid_non_lazy_types)))
+ raise ValueError("type must be %s"%(", ".join(valid_types)))
return key
#######################################################################################################
@@ -197,7 +247,7 @@ def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_se
# p-Adic Fields
# Qp -- base field
# Qq -- unramified extension field of Qp
-# QpCR, QpL, QqCR, QqL -- shortcuts for capped relative and lazy versions of Qp and Qq
+# QpCR, QpLC, QpLF, QqCR -- shortcuts for capped relative and lattice versions of Qp and Qq
#
#######################################################################################################
@@ -205,7 +255,7 @@ def get_key_base(p, prec, type, print_mode, names, ram_name, print_pos, print_se
padic_field_cache = {}
DEFAULT_PREC = Integer(20)
class Qp_class(UniqueFactory):
- """
+ r"""
A creation function for `p`-adic fields.
INPUT:
@@ -213,12 +263,15 @@ class Qp_class(UniqueFactory):
- ``p`` -- integer: the `p` in `\mathbb{Q}_p`
- ``prec`` -- integer (default: ``20``) the precision cap of the field.
- Individual elements keep track of their own precision. See
- TYPES and PRECISION below.
+ In the lattice capped case, ``prec`` can either be a
+ pair (``relative_cap``, ``absolute_cap``) or an integer
+ (understood at relative cap).
+ Except in the floating point case, individual elements keep track of
+ their own precision. See TYPES and PRECISION below.
- ``type`` -- string (default: ``'capped-rel'``) Valid types are
- ``'capped-rel'``, ``'floating-point'`` and ``'lazy'`` (though ``'lazy'`` currently
- doesn't work). See TYPES and PRECISION below
+ ``'capped-rel'``, ``'floating-point'``, ``'lattice-cap'``, ``'lattice-float'``.
+ See TYPES and PRECISION below
- ``print_mode`` -- string (default: ``None``). Valid modes are 'series',
'val-unit', 'terse', 'digits', and 'bars'. See PRINTING below
@@ -248,6 +301,9 @@ class Qp_class(UniqueFactory):
Non-prime input may cause seg-faults (but can also be useful for
base n expansions for example)
+ - ``label`` -- string (default ``None``) used for lattice precision to
+ create parents with different lattices.
+
OUTPUT:
- The corresponding `p`-adic field.
@@ -270,7 +326,7 @@ class Qp_class(UniqueFactory):
22
There are three types of `p`-adic fields: capped relative fields,
- floating point fields and lazy fields.
+ floating point fields and lattice precision fields.
In the capped relative case, the relative precision of an element
is restricted to be at most a certain value, specified at the
@@ -291,8 +347,9 @@ class Qp_class(UniqueFactory):
precision, but the relative precision of elements is truncated
during arithmetic to the precision cap of the field.
- The lazy case will eventually support elements that can increase
- their precision upon request. It is not currently implemented.
+ In the lattice case, precision on elements is tracked by a global
+ lattice that is updated after every operation, yielding better
+ precision behavior at the cost of higher memory and runtime usage.
PRINTING:
@@ -430,9 +487,9 @@ class Qp_class(UniqueFactory):
'...444444444444444341.33'
Observe that the significant 0's are printed even if they are
- located in front of the number. On the contrary, unknown digits
+ located in front of the number. On the contrary, unknown digits
located after the comma appears as question marks.
- The precision can therefore be read in this mode as well.
+ The precision can therefore be read in this mode as well.
Here are more examples::
sage: p = 7
@@ -537,8 +594,9 @@ class Qp_class(UniqueFactory):
"""
def create_key(self, p, prec = None, type = 'capped-rel', print_mode = None,
names = None, ram_name = None, print_pos = None,
- print_sep = None, print_alphabet = None, print_max_terms = None, show_prec=None, check = True):
- """
+ print_sep = None, print_alphabet = None, print_max_terms = None, show_prec = None, check = True,
+ label = None): # specific to Lattice precision
+ r"""
Creates a key from input parameters for ``Qp``.
See the documentation for ``Qp`` for more information.
@@ -546,7 +604,7 @@ class Qp_class(UniqueFactory):
TESTS::
sage: Qp.create_key(5,40)
- (5, 40, 'capped-rel', 'series', '5', True, '|', (), -1, True)
+ (5, 40, 'capped-rel', 'series', '5', True, '|', (), -1, True, None)
"""
if isinstance(names, (int, Integer)):
# old pickle; names is what used to be halt.
@@ -556,10 +614,12 @@ class Qp_class(UniqueFactory):
print_alphabet = print_max_terms
print_max_terms = check
check = True
- return get_