Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
r""" The functions in this file are used in creating new p-adic elements.
When creating a p-adic element, the user can specify that the absolute precision be bounded and/or that the relative precision be bounded. Moreover, different p-adic parents impose their own bounds on the relative or absolute precision of their elements. The precision determines to what power of `p` the defining data will be reduced, but the valuation of the resulting element needs to be determined before the element is created. Moreover, some defining data can impose their own precision bounds on the result.
AUTHORS:
- David Roe (2012-03-01) """
#***************************************************************************** # Copyright (C) 2007-2013 David Roe <roed.math@gmail.com> # William Stein <wstein@gmail.com> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import absolute_import
from cpython.int cimport * from sage.ext.stdsage cimport PY_NEW from sage.libs.gmp.all cimport * from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational from sage.rings.padics.padic_generic_element cimport pAdicGenericElement import sage.rings.finite_rings.integer_mod from cypari2.types cimport * from cypari2.gen cimport Gen as pari_gen from sage.rings.infinity import infinity from sage.structure.element cimport parent
cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) - 1 # The following Integer is used so that the functions here don't need to initialize an mpz_t. cdef Integer temp = PY_NEW(Integer)
cdef long get_ordp(x, PowComputer_class prime_pow) except? -10000: """ This function determines the valuation of the `p`-adic element that will result from the given data ``x``.
Note that the valuation can differ depending on the ring: if the new `p`-adic element is being created in a ring with ramification then the valuation will be larger.
Some preprocessing is done in the initialization methods of the element, so the type of x is restricted.
Also note that for some kinds of elements conversion to and from Integers and Rationals is done in a custom morphism rather than through this function.
INPUT:
- ``x`` -- data defining a new p-adic element: a Python int, an Integer, Rational, an element of Zp or Qp with the same prime, a PARI p-adic element, a list, a tuple, or an IntegerMod.
- a PowComputer associated to a `p`-adic ring, which determines the prime and the ramification degree.
OUTPUT:
- a long, giving the valuation of the resulting `p`-adic element. If the input is zero, returns ``maxordp`` """ cdef Integer value cdef GEN pari_tmp except OverflowError: return get_ordp(Integer(x), prime_pow) else: # x is not divisible by p k += 1 n = n / p # could reduce modulo the defining polynomial but that isn't currently supported raise ValueError("List too long") if e == 1 or f == 1: raise ValueError("nested lists not allowed for unramified and eisenstein extensions") for b in a: if isinstance(b, (list,tuple)): raise ValueError("list nesting too deep") curterm = get_ordp(b, prime_pow) k = min(k, curterm + shift) else: # We don't want to multiply by e again. else: # t_INT and t_FRAC were converted before this function raise TypeError("unsupported coercion from pari: only p-adics, integers and rationals allowed") else: raise NotImplementedError("Can not determine p-adic valuation of an element of %s"%parent(x)) # Should check for overflow
cdef long get_preccap(x, PowComputer_class prime_pow) except? -10000: """ This function determines the maximum absolute precision possible for an element created from the given data ``x``.
Note that the valuation can differ depending on the ring: if the new `p`-adic element is being created in a ring with ramification then the precision bound will be larger.
Some preprocessing is done in the initialization methods of the element, so the type of x is restricted.
Also note that for some kinds of elements conversion to and from Integers and Rationals is done in a custom morphism rather than through this function.
INPUT:
- ``x`` -- data defining a new p-adic element: an Integer, Rational, an element of Zp or Qp with the same prime, a PARI p-adic element, a list, a tuple, or an IntegerMod. - ``prime_pow`` -- the PowComputer for the ring into which ``x`` is being converted. This is used to determine the prime and the ramification degree.
OUTPUT:
- a long, giving the absolute precision modulo which the input is defined. If the input is exact, returns ``maxordp`` """ cdef Integer prec cdef GEN pari_tmp for b in a: curterm = get_preccap(b, prime_pow) k = min(k, curterm + shift) else: # We don't want to multiply by e again. # since x lives in a subfield, the ramification index of x's parent will divide e. # since get_ordp has been called typ(x.g) == t_PADIC raise TypeError("cannot coerce from the given integer mod ring (not a power of the same prime)") else: raise NotImplementedError("Can not determine p-adic precision of an element of %s"%parent(x))
cdef long comb_prec(iprec, long prec) except? -10000: """ This function returns the minimum of iprec and prec.
INPUT:
- ``iprec`` -- either infinity, an Integer, a Python int or something that can be converted to an Integer.
- ``prec`` -- a long. """ cdef Integer intprec raise OverflowError("precision overflow") return comb_prec(Integer(iprec), prec)
cdef int _process_args_and_kwds(long *aprec, long *rprec, args, kwds, bint absolute, PowComputer_class prime_pow) except -1: """ This function obtains values for absprec and relprec from a combination of positional and keyword arguments.
When creating a p-adic element, the user can pass in two arguments: ``absprec`` and ``relprec``. In implementing morphisms to speed up conversion from Integers and Rationals, we need to determine ``absprec`` and ``relprec`` from the ``args`` and ``kwds`` arguments of ``_call_with_args``. This function collects the code to do so.
INPUT:
- ``args`` -- a tuple of positional arguments (at most two)
- ``kwds`` -- a dictionary of keyword arguments (only ``'relprec'`` and ``'absprec'`` are used)
- ``absolute`` -- (boolean) True if the precision cap of the ring is a cap on absolute precision, False if a cap on relative precision.
- ``prime_pow`` -- a :class:`sage.rings.padics.pow_computer.PowComputer_class` instance
OUTPUT:
- ``aprec`` -- (first argument) the maximum absolute precision of the resulting element.
- ``rprec`` -- (second argument) the maximum relative precision of the resulting element.
- error status """ # For backward compatibility raise TypeError("too many positional arguments") raise TypeError("_call_with_args() got multiple values for keyword argument 'relprec'") else: raise TypeError("_call_with_args() got multiple values for keyword argument 'absprec'") else: else:
cdef inline long cconv_mpq_t_shared(mpz_t out, mpq_t x, long prec, bint absolute, PowComputer_class prime_pow) except? -10000: """ A fast pathway for conversion of rationals that doesn't require precomputation of the valuation.
INPUT:
- ``out`` -- an ``mpz_t`` to store the output. - ``x`` -- an ``mpq_t`` giving the integer to be converted. - ``prec`` -- a long, giving the precision desired: absolute or relative depending on the ``absolute`` input. - ``absolute`` -- if False then extracts the valuation and returns it, storing the unit in ``out``; if True then just reduces ``x`` modulo the precision. - ``prime_pow`` -- a PowComputer for the ring.
OUTPUT:
- If ``absolute`` is False then returns the valuation that was extracted (``maxordp`` when `x = 0`). """ cdef long numval, denval cdef bint success raise ValueError mpz_set_ui(out, 0) return maxordp else: else:
cdef inline int cconv_mpq_t_out_shared(mpq_t out, mpz_t x, long valshift, long prec, PowComputer_class prime_pow) except -1: """ Converts the underlying `p`-adic element into a rational
- ``out`` -- gives a rational approximating the input. Currently uses rational reconstruction but may change in the future to use a more naive method - ``x`` -- an ``mpz_t`` giving the underlying `p`-adic element - ``valshift`` -- a long giving the power of `p` to shift `x` by -` ``prec`` -- a long, the precision of ``x``, used in rational reconstruction - ``prime_pow`` -- a PowComputer for the ring """
# if valshift is nonzero then we starte with x as a p-adic unit, # so there will be no powers of p in the numerator or denominator # and the following operations yield reduced rationals.
cdef inline int cconv_shared(mpz_t out, x, long prec, long valshift, PowComputer_class prime_pow) except -2: """ Conversion from other Sage types.
INPUT:
- ``out`` -- an ``mpz_t`` to store the output.
- ``x`` -- a Sage element that can be converted to a `p`-adic element.
- ``prec`` -- a long, giving the precision desired: absolute if `valshift = 0`, relative if `valshift != 0`.
- ``valshift`` -- the power of the uniformizer to divide by before storing the result in ``out``.
- ``prime_pow`` -- a PowComputer for the ring.
""" raise RuntimeError("Integer should not have negative valuation") else: else: mpz_invert(out, mpq_denref((<Rational>x).value), prime_pow.pow_mpz_t_tmp(prec)) mpz_divexact(temp.value, mpq_numref((<Rational>x).value), prime_pow.pow_mpz_t_tmp(valshift)) mpz_mul(out, out, temp.value) elif isinstance(x, list): if valshift == 0: if len(x) == 0: cconv_shared(out, Integer(0), prec, valshift, prime_pow) elif len(x) == 1: cconv_shared(out, x[0], prec, valshift, prime_pow) else: raise NotImplementedError("conversion not implemented from non-prime residue field") else: raise NotImplementedError else: raise NotImplementedError("No conversion defined for %s which is a %s in %s"%(x,type(x),x.parent() if hasattr(x,"parent") else "no parent"))
cdef inline long cconv_mpz_t_shared(mpz_t out, mpz_t x, long prec, bint absolute, PowComputer_class prime_pow) except -2: """ A fast pathway for conversion of integers that doesn't require precomputation of the valuation.
INPUT:
- ``out`` -- an ``mpz_t`` to store the output. - ``x`` -- an ``mpz_t`` giving the integer to be converted. - ``prec`` -- a long, giving the precision desired: absolute or relative depending on the ``absolute`` input. - ``absolute`` -- if False then extracts the valuation and returns it, storing the unit in ``out``; if True then just reduces ``x`` modulo the precision. - ``prime_pow`` -- a PowComputer for the ring.
OUTPUT:
- If ``absolute`` is False then returns the valuation that was extracted (``maxordp`` when `x = 0`). """ cdef long val mpz_set_ui(out, 0) return maxordp else:
cdef inline int cconv_mpz_t_out_shared(mpz_t out, mpz_t x, long valshift, long prec, PowComputer_class prime_pow) except -1: """ Converts the underlying `p`-adic element into an integer if possible.
- ``out`` -- stores the resulting integer as an integer between 0 and `p^{prec + valshift}`. - ``x`` -- an ``mpz_t`` giving the underlying `p`-adic element. - ``valshift`` -- a long giving the power of `p` to shift `x` by. -` ``prec`` -- a long, the precision of ``x``: currently not used. - ``prime_pow`` -- a PowComputer for the ring. """ else: |