"""
`p`-Adic ``ZZ_pX`` CR Element

This file implements elements of Eisenstein and unramified extensions
of `\mathbb{Z}_p` and `\mathbb{Q}_p` with capped relative precision.

For the parent class see padic_extension_leaves.pyx.

The underlying implementation is through NTL's ``ZZ_pX`` class.  Each
element contains the following data:

- ``ordp`` (``long``) -- A power of the uniformizer to scale the unit
  by.  For unramified extensions this uniformizer is `p`, for Eisenstein
  extensions it is not.  A value equal to the maximum value of a long
  indicates that the element is an exact zero.

- ``relprec`` (``long``) -- A signed integer giving the precision to
  which this element is defined.  For nonzero ``relprec``, the
  absolute value gives the power of the uniformizer modulo which the
  unit is defined.  A positive value indicates that the element is
  normalized (ie ``unit`` is actually a unit: in the case of
  Eisenstein extensions the constant term is not divisible by `p`, in
  the case of unramified extensions that there is at least one
  coefficient that is not divisible by `p`).  A negative value
  indicates that the element may or may not be normalized.  A zero
  value indicates that the element is zero to some precision.  If so,
  ``ordp`` gives the absolute precision of the element.  If ``ordp``
  is greater than ``maxordp``, then the element is an exact zero.

- ``unit`` (``ZZ_pX_c``) -- An ntl ``ZZ_pX`` storing the unit part.
  The variable `x` is the uniformizer in the case of Eisenstein
  extensions. If the element is not normalized, the ``unit`` may or
  may not actually be a unit.  This ``ZZ_pX`` is created with global
  ntl modulus determined by the absolute value of ``relprec``.  If
  ``relprec`` is 0, ``unit`` **is not initialized**, or destructed if
  normalized and found to be zero.  Otherwise, let `r` be relprec and
  `e` be the ramification index over `\mathbb{Q}_p` or `\mathbb{Z}_p`.
  Then the modulus of unit is given by `p^{ceil(r/e)}`.  Note that all
  kinds of problems arise if you try to mix moduli.
  ``ZZ_pX_conv_modulus`` gives a semi-safe way to convert between
  different moduli without having to pass through ``ZZX`` (see
  ``sage/libs/ntl/decl.pxi`` and ``c_lib/src/ntl_wrap.cpp``)

- ``prime_pow`` (some subclass of ``PowComputer_ZZ_pX``) -- a class,
  identical among all elements with the same parent, holding common
  data.

  + ``prime_pow.deg`` -- The degree of the extension

  + ``prime_pow.e``   -- The ramification index

  + ``prime_pow.f``   -- The inertia degree

  + ``prime_pow.prec_cap`` -- the unramified precision cap.  For
    Eisenstein extensions this is the smallest power of p that is
    zero.

  + ``prime_pow.ram_prec_cap`` -- the ramified precision cap.  For
    Eisenstein extensions this will be the smallest power of `x` that
    is indistinguishable from zero.

  + ``prime_pow.pow_ZZ_tmp``, prime_pow.pow_mpz_t_tmp``,
    ``prime_pow.pow_Integer`` -- functions for accessing powers of
    `p`.  The first two return pointers.  See
    ``sage/rings/padics/pow_computer_ext`` for examples and important
    warnings.

  + ``prime_pow.get_context``, ``prime_pow.get_context_capdiv``,
    ``prime_pow.get_top_context`` -- obtain an
    ``ntl_ZZ_pContext_class`` corresponding to `p^n`.  The capdiv
    version divides by ``prime_pow.e`` as appropriate.
    ``top_context`` corresponds to `p^{prec_cap}`.

  + ``prime_pow.restore_context``,
    ``prime_pow.restore_context_capdiv``,
    ``prime_pow.restore_top_context`` -- restores the given context.

  + ``prime_pow.get_modulus``, ``get_modulus_capdiv``,
    ``get_top_modulus`` -- Returns a ``ZZ_pX_Modulus_c*`` pointing to
    a polynomial modulus defined modulo `p^n` (appropriately divided
    by ``prime_pow.e`` in the capdiv case).

EXAMPLES:

An Eisenstein extension::

    sage: R = Zp(5,5)
    sage: S.<x> = R[]
    sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
    sage: W.<w> = R.ext(f); W
    Eisenstein Extension of 5-adic Ring with capped relative precision 5 in w defined by (1 + O(5^5))*x^5 + (O(5^6))*x^4 + (3*5^2 + O(5^6))*x^3 + (2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))*x^2 + (5^3 + O(5^6))*x + (4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))
    sage: z = (1+w)^5; z
    1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
    sage: y = z >> 1; y
    w^4 + w^5 + 2*w^6 + 4*w^7 + 3*w^9 + w^11 + 4*w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^19 + w^20 + 4*w^23 + O(w^24)
    sage: y.valuation()
    4
    sage: y.precision_relative()
    20
    sage: y.precision_absolute()
    24
    sage: z - (y << 1)
    1 + O(w^25)
    sage: (1/w)^12+w
    w^-12 + w + O(w^13)
    sage: (1/w).parent()
    Eisenstein Extension of 5-adic Field with capped relative precision 5 in w defined by (1 + O(5^5))*x^5 + (O(5^6))*x^4 + (3*5^2 + O(5^6))*x^3 + (2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))*x^2 + (5^3 + O(5^6))*x + (4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))

Unramified extensions::

    sage: g = x^3 + 3*x + 3
    sage: A.<a> = R.ext(g)
    sage: z = (1+a)^5; z
    (2*a^2 + 4*a) + (3*a^2 + 3*a + 1)*5 + (4*a^2 + 3*a + 4)*5^2 + (4*a^2 + 4*a + 4)*5^3 + (4*a^2 + 4*a + 4)*5^4 + O(5^5)
    sage: z - 1 - 5*a - 10*a^2 - 10*a^3 - 5*a^4 - a^5
    O(5^5)
    sage: y = z >> 1; y
    (3*a^2 + 3*a + 1) + (4*a^2 + 3*a + 4)*5 + (4*a^2 + 4*a + 4)*5^2 + (4*a^2 + 4*a + 4)*5^3 + O(5^4)
    sage: 1/a
    (3*a^2 + 4) + (a^2 + 4)*5 + (3*a^2 + 4)*5^2 + (a^2 + 4)*5^3 + (3*a^2 + 4)*5^4 + O(5^5)
    sage: FFp = R.residue_field()
    sage: R(FFp(3))
    3 + O(5)
    sage: QQq.<zz> = Qq(25,4)
    sage: QQq(FFp(3))
    3 + O(5)
    sage: FFq = QQq.residue_field(); QQq(FFq(3))
    3 + O(5)
    sage: zz0 = FFq.gen(); QQq(zz0^2)
    (zz + 3) + O(5)

Different printing modes::

    sage: R = Zp(5, print_mode='digits'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
    sage: z = (1+w)^5; repr(z)
    '...4110403113210310442221311242000111011201102002023303214332011214403232013144001400444441030421100001'
    sage: R = Zp(5, print_mode='bars'); S.<x> = R[]; g = x^3 + 3*x + 3; A.<a> = R.ext(g)
    sage: z = (1+a)^5; repr(z)
    '...[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 4, 4]|[4, 3, 4]|[1, 3, 3]|[0, 4, 2]'
    sage: R = Zp(5, print_mode='terse'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
    sage: z = (1+w)^5; z
    6 + 95367431640505*w + 25*w^2 + 95367431640560*w^3 + 5*w^4 + O(w^100)
    sage: R = Zp(5, print_mode='val-unit'); S.<x> = R[]; f = x^5 + 75*x^3 - 15*x^2 + 125*x -5; W.<w> = R.ext(f)
    sage: y = (1+w)^5 - 1; y
    w^5 * (2090041 + 19073486126901*w + 1258902*w^2 + 674*w^3 + 16785*w^4) + O(w^100)

You can get at the underlying ntl unit::

    sage: z._ntl_rep()
    [6 95367431640505 25 95367431640560 5]
    sage: y._ntl_rep()
    [2090041 19073486126901 1258902 674 16785]
    sage: y._ntl_rep_abs()
    ([5 95367431640505 25 95367431640560 5], 0)

NOTES::

    If you get an error ``internal error: can't grow this
    _ntl_gbigint,`` it indicates that moduli are being mixed
    inappropriately somewhere.  For example, when calling a function
    with a ``ZZ_pX_c`` as an argument, it copies.  If the modulus is not
    set to the modulus of the ``ZZ_pX_c``, you can get errors.

AUTHORS:

- David Roe (2008-01-01): initial version

- Robert Harron (2011-09): fixes/enhancements

- Julian Rueth (2014-05-09): enable caching through ``_cache_key``

"""

#*****************************************************************************
#       Copyright (C) 2008 David Roe <roed.math@gmail.com>
#                          William Stein <wstein@gmail.com>
#                     2014 Julian Rueth <julian.rueth@fsfe.org>
#
#  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/
#*****************************************************************************

include "sage/ext/stdsage.pxi"
include "sage/ext/interrupt.pxi"

from sage.rings.integer cimport Integer
from sage.rings.rational cimport Rational
from sage.libs.ntl.ntl_ZZX cimport ntl_ZZX
from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p
from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class
from sage.libs.ntl.ntl_ZZ_pContext import ntl_ZZ_pContext
from sage.rings.padics.padic_generic_element cimport pAdicGenericElement
from sage.libs.pari.all import pari_gen
from sage.interfaces.gp import GpElement
from sage.rings.finite_rings.integer_mod import is_IntegerMod
from sage.rings.padics.padic_ext_element cimport pAdicExtElement
from sage.rings.padics.precision_error import PrecisionError

from sage.rings.padics.pow_computer_ext cimport PowComputer_ZZ_pX
from sage.rings.padics.pow_computer_ext cimport PowComputer_ZZ_pX_small_Eis
from sage.rings.padics.pow_computer_ext cimport PowComputer_ZZ_pX_big_Eis
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
from sage.rings.padics.unramified_extension_generic import UnramifiedExtensionGeneric

from sage.rings.real_double cimport RealDoubleElement

cdef object infinity
from sage.rings.infinity import infinity

cdef long maxordp = (1L << (sizeof(long) * 8 - 2)) -1
cdef long minusmaxordp = -maxordp

cdef inline int check_ordp(long a) except -1:
    if a > maxordp or a < minusmaxordp:
        raise ValueError, "valuation overflow"


cdef class pAdicZZpXCRElement(pAdicZZpXElement):
    def __init__(self, parent, x, absprec = infinity, relprec = infinity, empty = False):
        """
        Creates an element of a capped relative precision, unramified
        or Eisenstein extension of `\mathbb{Z}_p` or `\mathbb{Q}_p`.

        INPUT:

        - ``parent`` -- either an ``EisensteinRingCappedRelative`` or
          ``UnramifiedRingCappedRelative``

        - ``x`` -- an integer, rational, `p`-adic element, polynomial,
          list, integer_mod, pari int/frac/poly_t/pol_mod, an
          ``ntl_ZZ_pX``, an ``ntl_ZZ``, an ``ntl_ZZ_p``, an
          ``ntl_ZZX``, or something convertible into parent.residue_field()

        - ``absprec`` -- an upper bound on the absolute precision of the
          element created

        - ``relprec`` -- an upper bound on the relative precision of
          the element created

        - ``empty`` -- whether to return after initializing to zero
          (without setting the valuation).

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1+w)^5; z # indirect doctest
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: W(pari('3 + O(5^3)'))
            3 + O(w^15)
            sage: W(R(3,3))
            3 + O(w^15)
            sage: W.<w> = R.ext(x^625 + 915*x^17 - 95)
            sage: W(3)
            3 + O(w^3125)
            sage: W(w, 14)
            w + O(w^14)

        TESTS:

        Check that :trac:`3865` is fixed::

            sage: W(gp('3 + O(5^10)'))
            3 + O(w^3125)


        Check that :trac:`13612` has been fixed::

            sage: R = Zp(3)
            sage: S.<a> = R[]
            sage: W.<a> = R.extension(a^2+1)
            sage: W(W.residue_field().zero())
            O(3)

            sage: K = Qp(3)
            sage: S.<a> = K[]
            sage: L.<a> = K.extension(a^2+1)
            sage: L(L.residue_field().zero())
            O(3)

        """
        pAdicZZpXElement.__init__(self, parent)
        self.relprec = 0
        if empty:
            return
        cdef long aprec, rprec, ctx_prec, ltmp
        if relprec is not infinity and not PY_TYPE_CHECK(relprec, Integer):
            relprec = Integer(relprec)
        if (relprec is infinity) or (relprec > parent.precision_cap()):
            rprec = self.prime_pow.ram_prec_cap
        else:
            rprec = mpz_get_si((<Integer>relprec).value)
        if rprec < 0:
            rprec = 0
        if absprec is not infinity:
            if not PY_TYPE_CHECK(absprec, Integer):
                absprec = Integer(absprec)
            if mpz_fits_slong_p((<Integer>absprec).value) == 0:
                absprec = infinity
            else:
                aprec = mpz_get_si((<Integer>absprec).value)
        cdef mpz_t tmp
        cdef ZZ_c tmp_z
        cdef Py_ssize_t i
        cdef Integer tmp_Int
        cdef Rational xlift
        if PY_TYPE_CHECK(x, pAdicGenericElement):
            if self.prime_pow.in_field == 0 and x.valuation() < 0:
                raise ValueError, "element has negative valuation"
            if x._is_base_elt(self.prime_pow.prime):
                xlift = Rational(x.lift())
                if mpq_sgn(xlift.value) == 0:
                    if (<pAdicGenericElement>x)._is_exact_zero():
                        if absprec is infinity:
                            self._set_exact_zero()
                        else:
                            self._set_inexact_zero(aprec)
                        return
                ltmp = mpz_get_si((<Integer>x.precision_absolute()).value) * self.prime_pow.e
                if absprec is infinity or ltmp < aprec:
                    aprec = ltmp
                self._set_from_mpq_both(xlift.value, aprec, rprec)
                return
        if isinstance(x, GpElement):
            x = x._pari_()
        if isinstance(x, pari_gen):
            if x.type() == "t_PADIC":
                if x.variable() != self.prime_pow.prime:
                    raise TypeError, "Cannot coerce a pari p-adic with the wrong prime."
                ltmp = x.padicprec(self.prime_pow.prime) * self.prime_pow.e
                if absprec is infinity or ltmp < aprec:
                    aprec = ltmp
                    absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
                x = x.lift()
            if x.type() == 't_INT':
                x = Integer(x)
            elif x.type() == 't_FRAC':
                x = Rational(x)
            elif x.type() == 't_POLMOD' or x.type == 't_POL':
                # This code doesn't check to see if the primes are the same.
                L = []
                x = x.lift().lift()
                for i from 0 <= i <= x.poldegree():
                    L.append(Integer(x.polcoeff(i)))
                x = L
            else:
                raise TypeError, "unsupported coercion from pari: only p-adics, integers, rationals, polynomials and pol_mods allowed"
        elif is_IntegerMod(x):
            mpz_init(tmp)
            ctx_prec = mpz_remove(tmp, (<Integer>x.modulus()).value, self.prime_pow.prime.value)
            if mpz_cmp_ui(tmp, 1) == 0:
                mpz_clear(tmp)
                x = x.lift()
                if absprec is infinity or ctx_prec < aprec:
                    aprec = ctx_prec
                    absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
            else:
                mpz_clear(tmp)
                raise TypeError, "cannot coerce from the given integer mod ring (not a power of the same prime)"
        elif PY_TYPE_CHECK(x, ntl_ZZ_p):
            ctx_prec = ZZ_remove(tmp_z, (<ntl_ZZ>x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0])
            if ZZ_IsOne(tmp_z):
                x = x.lift()
                tmp_Int = PY_NEW(Integer)
                ZZ_to_mpz(tmp_Int.value, &(<ntl_ZZ>x).x)
                x = tmp_Int
                if absprec is infinity or ctx_prec < aprec:
                    aprec = ctx_prec
                    absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
            else:
                raise TypeError, "cannot coerce the given ntl_ZZ_p (modulus not a power of the same prime)"
        elif PY_TYPE_CHECK(x, ntl_ZZ):
            tmp_Int = PY_NEW(Integer)
            ZZ_to_mpz(tmp_Int.value, &(<ntl_ZZ>x).x)
            x = tmp_Int
        elif isinstance(x, (int, long)):
            x = Integer(x)
        elif x in parent.residue_field():
            # Should only reach here if x is not in F_p
            z = parent.gen()
            poly = x.polynomial().list()
            x = sum([poly[i].lift() * (z ** i) for i in range(len(poly))], parent.zero())
            if absprec is infinity or 1 < aprec:
                aprec = 1
                absprec = 0 # absprec just has to be non-infinite: everything else uses aprec
        cdef pAdicZZpXCRElement _x
        if PY_TYPE_CHECK(x, Integer):
            if absprec is infinity:
                self._set_from_mpz_rel((<Integer>x).value, rprec)
            else:
                self._set_from_mpz_both((<Integer>x).value, aprec, rprec)
        elif PY_TYPE_CHECK(x, Rational):
            if absprec is infinity:
                self._set_from_mpq_rel((<Rational>x).value, rprec)
            else:
                self._set_from_mpq_both((<Rational>x).value, aprec, rprec)
        elif PY_TYPE_CHECK(x, ntl_ZZ_pX):
            if absprec is infinity:
                self._set_from_ZZ_pX_rel(&(<ntl_ZZ_pX>x).x, (<ntl_ZZ_pX>x).c, rprec)
            else:
                self._set_from_ZZ_pX_both(&(<ntl_ZZ_pX>x).x, (<ntl_ZZ_pX>x).c, aprec, rprec)
        elif PY_TYPE_CHECK(x, ntl_ZZX):
            if absprec is infinity:
                self._set_from_ZZX_rel((<ntl_ZZX>x).x, rprec)
            else:
                self._set_from_ZZX_both((<ntl_ZZX>x).x, aprec, rprec)
        elif PY_TYPE_CHECK(x, pAdicExtElement):
            if x.parent() is parent:
                _x = <pAdicZZpXCRElement>x
                if _x.relprec == 0:
                    if absprec is infinity or aprec > _x.ordp:
                        self._set_inexact_zero(_x.ordp) # this works for exact zeros too.
                    else:
                        self._set_inexact_zero(aprec)
                elif _x.relprec < 0:
                    if -_x.relprec < rprec:
                        rprec = _x.relprec
                    else:
                        rprec = -rprec
                    if absprec is infinity or aprec > _x.ordp - rprec:
                        self._set(&_x.unit, _x.ordp, rprec)
                    elif aprec > _x.ordp:
                        self._set(&_x.unit, _x.ordp, _x.ordp - aprec) #negating relprec to indicate non-normalized.
                    else:
                        self._set_inexact_zero(aprec)
                else:
                    if _x.relprec < rprec:
                        rprec = _x.relprec
                    if absprec is infinity or aprec > _x.ordp + rprec:
                        self._set(&_x.unit, _x.ordp, rprec)
                    elif aprec > _x.ordp:
                        self._set(&_x.unit, _x.ordp, aprec - _x.ordp)
                    else:
                        self._set_inexact_zero(aprec)
            elif x.parent().fraction_field() is parent:
                if PY_TYPE_CHECK(x, pAdicZZpXCRElement):
                    _x = <pAdicZZpXCRElement>x
                    if _x.relprec < 0:
                        _x._normalize()
                    if _x._is_exact_zero():
                        self._set_exact_zero()
                    elif _x._is_inexact_zero():
                        self._set_inexact_zero(_x.ordp)
                    else:
                        if _x.relprec < rprec:
                            rprec = _x.relprec
                        self._set(&_x.unit, _x.ordp, rprec)
                else:
                    # x is a pAdicZZpXCAElement
                    xordp = x.valuation()
                    xprec = x.precision_absolute()
                    if xordp == xprec:
                        self._set_inexact_zero(mpz_get_si((<Integer>xordp).value))
                    else:
                        poly = x._ntl_rep_abs()[0]
                        if absprec is infinity:
                            self._set_from_ZZ_pX_rel(&(<ntl_ZZ_pX>poly).x,(<ntl_ZZ_pX>poly).c, rprec)
                        else:
                            self._set_from_ZZ_pX_both(&(<ntl_ZZ_pX>poly).x,(<ntl_ZZ_pX>poly).c, aprec, rprec)
            elif x.parent() is parent.fraction_field():
                _x = <pAdicZZpXCRElement>x
                if _x.relprec < 0:
                    _x._normalize()
                if _x._is_exact_zero():
                    self._set_exact_zero()
                elif _x._is_inexact_zero():
                    self._set_inexact_zero(_x.ordp)
                else:
                    if _x.relprec < rprec:
                        rprec = _x.relprec
                    self._set(&_x.unit, _x.ordp, rprec)
            else:
                raise NotImplementedError, "Conversion from different p-adic extensions not yet supported"
        else:
            try:
                x = list(x)
            except TypeError:
                try:
                    x = x.list()
                except AttributeError:
                    raise TypeError, "cannot convert x to a p-adic element"
            if absprec is infinity:
                self._set_from_list_rel(x, rprec)
            else:
                self._set_from_list_both(x, aprec, rprec)

    def _cache_key(self):
        r"""
        Return a hashable key which identifies this element.

        This makes it possible to use this element in caches such as
        functions or methods decorated with ``@cached_function`` or
        ``@cached_method`` respectively.

        EXAMPLE:

        In the following example, ``a`` and ``b`` compare equal. They cannot
        have a meaningful hash value since then their hash value would have to
        be the same::

            sage: K.<a> = Qq(9)
            sage: b = a + O(3)
            sage: a == b
            True
            sage: hash(a)
            Traceback (most recent call last):
            ...
            TypeError: unhashable type: 'sage.rings.padics.padic_ZZ_pX_CR_element.pAdicZZpXCRElement'

        However, we want to cache computations which depend on them. Therefore
        they define a ``_cache_key`` which is hashable and uniquely identifies
        them::

            sage: a._cache_key()
            (..., ((0, 1),), 0, 20)
            sage: b._cache_key()
            (..., ((0, 1),), 0, 1)

        TESTS:

        Check that zero values are handled correctly::

            sage: K.zero()._cache_key()
            (..., 0)
            sage: K(0,1)._cache_key()
            (..., 0, 1)

        """
        if self._is_exact_zero():
            return (self.parent(), 0)
        elif self._is_inexact_zero():
            return (self.parent(), 0, self.valuation())
        else:
            return (self.parent(),
                    tuple(tuple(c) if isinstance(c, list) else c
                          for c in self.unit_part().list()),
                    self.valuation(), self.precision_relative())

    cdef int _set_inexact_zero(self, long absprec) except -1:
        """
        Sets ``self`` to be zero with valuation absprec.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(0,6); z # indirect doctest
            O(w^6)
            sage: z.valuation()
            6
            sage: z.precision_absolute()
            6
            sage: z.precision_relative()
            0

        TESTS::

            sage: R = Zp(17, 3)
            sage: S.<x> = R[]
            sage: W.<w> = R.ext(x^34 - 289*x^5 + 17)
            sage: z = W(0, 6); z
            O(w^6)
            sage: z.valuation()
            6
            sage: z.precision_absolute()
            6
            sage: z.precision_relative()
            0
        """
        self.ordp = absprec
        self.relprec = 0

    cdef int _set_exact_zero(self) except -1:
        """
        Sets ``self`` to be an exact zero.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = R(0); z # indirect doctest
            0
            sage: z.valuation()
            +Infinity
            sage: z.precision_absolute()
            +Infinity
            sage: z.precision_relative()
            0

        TESTS::

            sage: R = Zp(89, 3)
            sage: S.<x> = R[]
            sage: W.<w> = R.ext(x^34 - 2*89*x^5 + 89)
            sage: z = R(0); z # indirect doctest
            0
            sage: z.valuation()
            +Infinity
            sage: z.precision_absolute()
            +Infinity
            sage: z.precision_relative()
            0
        """
        self.ordp = maxordp
        self.relprec = 0

    cpdef bint _is_exact_zero(self) except -1:
        """
        Tests if ``self`` is an exact zero.

        EXAMPLES::

            sage: R = Qp(3,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(0)
            sage: z._is_exact_zero()
            True
            sage: z = W(0,6)
            sage: z._is_exact_zero()
            False

        TESTS::

            sage: R = Qp(53, 3)
            sage: S.<x> = R[]
            sage: W.<w> = R.ext(x^34 - 2*53^5*x^9 + 53)
            sage: z = W(0)
            sage: z._is_exact_zero()
            True
            sage: z = W(0,6)
            sage: z._is_exact_zero()
            False

        """
        if self.ordp == maxordp:
            return 1
        else:
            return 0

    cpdef bint _is_inexact_zero(self) except -1:
        """
        Tests if ``self`` is an inexact zero.

        EXAMPLES::

            sage: R = Zp(7,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(0)
            sage: z._is_inexact_zero()
            False
            sage: z = W(0,6)
            sage: z._is_inexact_zero()
            True

        TESTS::

            sage: R = Qp(29, 3)
            sage: S.<x> = R[]
            sage: W.<w> = R.ext(x^29 - 2*29^5*x - 29)
            sage: z = W(0)
            sage: z._is_inexact_zero()
            False
            sage: z = W(0,6)
            sage: z._is_inexact_zero()
            True
        """
        self._normalize()
        if self.relprec == 0:
            return not self._is_exact_zero()
        else:
            return False

    cdef int _set(self, ZZ_pX_c* unit, long ordp, long relprec) except -1:
        """
        Sets ``unit``, ``ordp`` and ``relprec`` directly.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: F = W.fraction_field()
            sage: z = F(1+w); z # indirect doctest
            1 + w + O(w^25)

        TESTS::

            sage: R = Zp(17,30)
            sage: S.<x> = R[]
            sage: f = x^51 - 34
            sage: W.<w> = R.ext(f)
            sage: F = W.fraction_field()
            sage: z = F(1+w); z # indirect doctest
            1 + w + O(w^1530)
            sage: z = F(w+w^2,relprec=0); z
            O(w)
        """
        self.ordp = ordp
        self._set_prec_rel(relprec)
        if self.relprec != 0:
            ZZ_pX_conv_modulus(self.unit, unit[0], self.prime_pow.get_context_capdiv(relprec).x)

    cdef int _set_from_mpz_rel(self, mpz_t x, long relprec) except -1:
        """
        Sets ``self`` from an ``mpz_t`` with relative precision bounded by ``relprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: W(70, relprec = 8) # indirect doctest
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)
            sage: W(70, relprec = 0)
            O(w^5)

        TESTS::

            sage: R = Qp(13,50)
            sage: S.<x> = R[]
            sage: f = x^169 - 13
            sage: W.<w> = R.ext(f)
            sage: a = W(65, relprec = 8); a.valuation() # indirect doctest
            169
            sage: W(65, relprec = 0)
            O(w^169)
        """
        if mpz_sgn(x) == 0:
            self._set_exact_zero()
            return 0
        cdef mpz_t tmp_m
        cdef ZZ_c tmp_z
        cdef long shift
        mpz_init(tmp_m)
        sig_on()
        shift = mpz_remove(tmp_m, x, self.prime_pow.prime.value)
        sig_off()
        self._set_prec_rel(relprec)
        mpz_to_ZZ(&tmp_z, tmp_m)
        mpz_clear(tmp_m)
        if self.relprec != 0:
            ZZ_pX_SetCoeff(self.unit, 0, ZZ_to_ZZ_p(tmp_z))
            self.ordp = 0
            self._pshift_self(shift)
        else:
            self.ordp = shift * self.prime_pow.e

    cdef int _set_from_mpz_both(self, mpz_t x, long absprec, long relprec) except -1:
        """
        Sets ``self`` from an ``mpz_t`` with relative precision bounded by ``relprec``
        and absolute precision bounded by ``absprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: W(70, 8) # indirect doctest
            4*w^5 + 3*w^7 + O(w^8)
            sage: W(70, absprec = 4)
            O(w^4)

        TESTS::

            sage: R = Zp(7,3)
            sage: S.<x> = R[]
            sage: f = x^49 + 7*x^21 - 14
            sage: W.<w> = R.ext(f)
            sage: W(70, 100) # indirect doctest
            5*w^49 + 6*w^70 + 3*w^91 + O(w^100)
            sage: W(70, absprec = 4)
            O(w^4)
        """
        if mpz_sgn(x) == 0:
            self._set_inexact_zero(absprec)
            return 0
        cdef mpz_t tmp_m
        cdef ZZ_c tmp_z
        cdef long shift
        mpz_init(tmp_m)
        sig_on()
        shift = mpz_remove(tmp_m, x, self.prime_pow.prime.value)
        sig_off()
        self.ordp = shift * self.prime_pow.e
        if self._set_prec_both(absprec, relprec) == 1:
            # This indicates that self._set_inexact_zero was called
            mpz_clear(tmp_m)
            return 0
        mpz_to_ZZ(&tmp_z, tmp_m)
        mpz_clear(tmp_m)
        if self.relprec != 0:
            ZZ_pX_SetCoeff(self.unit, 0, ZZ_to_ZZ_p(tmp_z))
            self.ordp = 0
            self._pshift_self(shift)

    cdef int _set_from_mpq_rel(self, mpq_t x, long relprec) except -1:
        """
        Sets ``self`` from an ``mpq_t`` with relative precision
        bounded by ``relprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(70/3, relprec = 9); z # indirect doctest
            3*w^5 + w^7 + 2*w^9 + 2*w^10 + 4*w^11 + w^12 + 2*w^13 + O(w^14)
            sage: z * 3
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + O(w^14)
            sage: W(70)
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + 3*w^16 + w^17 + w^18 + 4*w^20 + 4*w^21 + w^22 + 2*w^23 + 3*w^25 + w^27 + O(w^30)
            sage: F = W.fraction_field()
            sage: y = F(3/700); y
            w^-10 + w^-8 + 4*w^-6 + w^-3 + 4*w^-2 + 3*w^-1 + 3 + 4*w + w^3 + 4*w^4 + w^5 + 4*w^6 + 2*w^7 + 3*w^8 + 4*w^9 + 3*w^10 + 4*w^11 + w^12 + O(w^15)
            sage: y * 700
            3 + O(w^25)
            sage: W(70/3, relprec = 0)
            O(w^5)
            sage: c = F(5^-1 + O(5^2)); c
            w^-5 + 3*w^-3 + 2*w^3 + 4*w^5 + 4*w^6 + 3*w^7 + w^9 + O(w^10)
            sage: c * 5
            1 + O(w^15)

        TESTS::

            sage: R = Zp(11, 8, print_mode='digits')
            sage: S.<x> = R[]
            sage: f = x^3 + 1331 * x^2 - 11 * x + 11
            sage: W.<w> = R.ext(f)
            sage: z = W(77/3, relprec = 11); repr(z)[3:]
            '304107A2555000'
            sage: repr(z*3)[3:]
            '56698765444000'
            sage: repr(W(77))[3:]
            '5800A6604678856698765444000'
            sage: F = W.fraction_field()
            sage: y = F(3/847); repr(y)[3:]
            '5563A4105291255628.148272'
            sage: repr(y*847)[3:]
            '3'
            sage: repr(W(77/3, relprec=0))[3:]
            ''
            sage: c = F(11^-1 + O(11^2)); repr(c)[3:]
            '11111.01A'
            sage: repr(c * 11)[3:]
            '1'
        """
        if mpq_sgn(x) == 0:
            self._set_exact_zero()
            return 0
        cdef mpz_t num_unit, den_unit
        self._set_from_mpq_part1(num_unit, den_unit, x)
        self._set_prec_rel(relprec)
        self._set_from_mpq_part2(num_unit, den_unit)

    cdef int _set_from_mpq_both(self, mpq_t x, long absprec, long relprec) except -1:
        """
        Sets ``self`` from an ``mpq_t`` with relative precision
        bounded by ``relprec`` and absolute precision bounded by
        ``absprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(70/3, 14); z # indirect doctest
            3*w^5 + w^7 + 2*w^9 + 2*w^10 + 4*w^11 + w^12 + 2*w^13 + O(w^14)
            sage: z * 3
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + O(w^14)
            sage: W(70)
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + w^13 + 3*w^16 + w^17 + w^18 + 4*w^20 + 4*w^21 + w^22 + 2*w^23 + 3*w^25 + w^27 + O(w^30)
            sage: F = W.fraction_field()
            sage: y = F(3/700,-2); y
            w^-10 + w^-8 + 4*w^-6 + w^-3 + O(w^-2)
            sage: y * 700
            3 + O(w^8)
            sage: W(70/3, absprec = 4)
            O(w^4)
        """
        if mpq_sgn(x) == 0:
            self._set_inexact_zero(absprec)
            return 0
        cdef mpz_t num_unit, den_unit
        self._set_from_mpq_part1(num_unit, den_unit, x)
        if self._set_prec_both(absprec, relprec) == 1:
            # indicates an inexact zero
            mpz_clear(num_unit)
            mpz_clear(den_unit)
            return 0
        self._set_from_mpq_part2(num_unit, den_unit)

    cdef int _set_from_mpq_part1(self, mpz_t num_unit, mpz_t den_unit, mpq_t x) except -1:
        """
        Sets ``num_unit`` to be the unit of the numerator, ``den_unit`` to be the unit of the denominator and sets ``self.ordp`` correctly.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(7000/3, 23); z # indirect doctest
            2*w^15 + 2*w^17 + 3*w^19 + w^22 + O(w^23)
        """
        cdef long num_ordp, den_ordp
        sig_on()
        mpz_init(num_unit)
        mpz_init(den_unit)
        num_ordp = mpz_remove(num_unit, mpq_numref(x), self.prime_pow.prime.value)
        den_ordp = mpz_remove(den_unit, mpq_denref(x), self.prime_pow.prime.value)
        sig_off()
        self.ordp = (num_ordp - den_ordp) * self.prime_pow.e
        if self.ordp < 0 and self.prime_pow.in_field == 0:
            mpz_clear(num_unit)
            mpz_clear(den_unit)
            raise ValueError, "p divides the denominator"

    cdef int _set_from_mpq_part2(self, mpz_t num_unit, mpz_t den_unit) except -1:
        """
        Given that ``self.ordp`` and ``self.relprec`` have been set, takes
        ``num_unit`` and ``den_unit`` and sets ``self.unit``.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: W(QQ(0), 23) # indirect doctest
            O(w^23)
            sage: W(QQ(0))
            0
        """
        cdef ZZ_c num_zz, den_zz
        cdef ZZ_p_c tmp_zp
        cdef long val = self.ordp / self.prime_pow.e
        cdef mpz_t tmp_m
        if self.relprec != 0:
            mpz_init(tmp_m)
            mpz_set(tmp_m, num_unit)
            mpz_to_ZZ(&num_zz, tmp_m)
            mpz_set(tmp_m, den_unit)
            mpz_to_ZZ(&den_zz, tmp_m)
            mpz_clear(tmp_m)
            #The context has been restored in setting self.relprec
            ZZ_p_div(tmp_zp, ZZ_to_ZZ_p(num_zz), ZZ_to_ZZ_p(den_zz))
            ZZ_pX_SetCoeff(self.unit, 0, tmp_zp)
            self.ordp = 0
            self._pshift_self(val)

    cdef int _set_from_ZZX_rel(self, ZZX_c poly, long relprec) except -1:
        """
        Sets ``self`` from a ``ZZX`` with relative precision bounded by
        ``relprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZX([4,1,16]), relprec = 14); z # indirect doctest
            4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + 4*w^13 + O(w^14)
            sage: z._ntl_rep()
            [4 1 16]
            sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), relprec = 14); z
            w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + O(w^214)
            sage: W(5)^40 + w*W(5)^42 + w^2 * W(3) * W(5)^41
            w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + 2*w^215 + w^217 + 2*w^218 + w^220 + w^221 + w^222 + 3*w^224 + O(w^225)
            sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), relprec = 0); z
            O(w^200)
        """
        if ZZX_IsZero(poly):
            self._set_exact_zero()
            return 0
        if ZZX_deg(poly) >= self.prime_pow.deg:
            raise NotImplementedError
        # the -1 in the next line signals that there is no absprec specified
        self._set_from_ZZX_part1(poly, -1, relprec)
        # context was restored in _set_from_ZZX_part1
        if relprec == 0:
            self._set_prec_rel(relprec)
            return 0
        if self.relprec + self.ordp != 0:
            self.prime_pow.restore_context_capdiv(self.relprec + self.ordp)
            ZZX_to_ZZ_pX(self.unit, poly)
            self._internal_lshift(-self.ordp)

    cdef int _set_from_ZZX_both(self, ZZX_c poly, long absprec, long relprec) except -1:
        """
        Sets ``self`` from a ``ZZX`` with relative precision bounded by
        ``relprec`` and absolute precision bounded by ``absprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZX([4,1,16]), 12); z # indirect doctest
            4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + O(w^12)
            sage: z._ntl_rep()
            [4 1 16]
            sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), 212); z
            w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + O(w^212)
            sage: z = W(ntl.ZZX([5^40,5^42,3*5^41]), 197); z
            O(w^197)
        """
        if ZZX_IsZero(poly) or absprec <= 0:
            self._set_inexact_zero(absprec)
            return 0
        if ZZX_deg(poly) >= self.prime_pow.deg:
            raise NotImplementedError
        if self._set_from_ZZX_part1(poly, absprec, relprec) == -2:
            # indicates _set_inexact_zero was called
            return 0
        # context was restored in _set_from_ZZX_part1
        if self.relprec + self.ordp != 0:
            self.prime_pow.restore_context_capdiv(self.relprec + self.ordp)
            ZZX_to_ZZ_pX(self.unit, poly)
            self._internal_lshift(-self.ordp)

    cdef int _set_from_ZZX_part1(self, ZZX_c poly, long absprec, long relprec) except -1:
        """
        Sets ``self.ordp`` from ``poly`` and restores the context.  ``poly`` must
        have degree less than ``self.prime_pow.deg``

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZX([4,1,16]), 12); z # indirect doctest
            4 + w + w^2 + 3*w^7 + w^9 + 2*w^11 + O(w^12)
        """
        cdef long i = 0
        cdef long deg = ZZX_deg(poly)
        cdef long mini = -1
        cdef long minval
        cdef long curval
        cdef ZZ_c tmp_z
        while mini == -1:
            if not ZZ_IsZero(ZZX_coeff(poly,i)):
                minval = ZZ_remove(tmp_z, ZZX_coeff(poly, i), self.prime_pow.pow_ZZ_tmp(1)[0])
                mini = i
            i += 1
        while i <= deg:
            if not ZZ_IsZero(ZZX_coeff(poly,i)):
                curval = ZZ_remove(tmp_z, ZZX_coeff(poly, i), self.prime_pow.pow_ZZ_tmp(1)[0])
                if curval < minval:
                    minval = curval
                    mini = i
            i += 1
        if self.prime_pow.e == 1:
            self.ordp = minval
        else:
            self.ordp = minval * self.prime_pow.e + mini
        if absprec == -1: # indicates that _set_from_ZZX_rel is calling
            self._set_prec_rel(relprec)
        elif self._set_prec_both(absprec, relprec):
            # indicates self._set_inexact_zero was called
            return -2
        # _set_prec_rel or both has restored the context so that part2 works.

    cdef int _set_from_ZZ_pX_rel(self, ZZ_pX_c* poly, ntl_ZZ_pContext_class ctx, long relprec) except -1:
        """
        Sets ``self`` from a ``ZZ_pX`` with relative precision bounded by
        ``relprec``.

        If ``ctx`` is ``None`` and ``poly`` is 0 this function will raise an error
        (a ``ZZ_pX`` cannot represent something with infinite absolute
        precision).

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZ_pX([4,1,16],5^2)); z # indirect doctest
            4 + w + w^2 + 3*w^7 + w^9 + O(w^10)
            sage: z._ntl_rep()
            [4 1 16]
            sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^44)); z
            w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + 2*w^215 + w^217 + 2*w^218 + O(w^220)
            sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^44), relprec = 0); z
            O(w^200)
        """
        cdef long ctx_prec = -1
        if ctx is not None:
            ctx_prec = self._check_ZZ_pContext(ctx) * self.prime_pow.e
        if ZZ_pX_IsZero(poly[0]):
            if ctx_prec == -1:
                raise ValueError, "must specify either a context or an absolute precision bound"
            else:
                self._set_inexact_zero(ctx_prec)
            return 0
        self._set_from_ZZ_pX_part1(poly)
        if relprec == 0:
            self._set_prec_rel(relprec)
            return 0
        if ctx_prec == -1:
            self._set_prec_rel(self.ordp + relprec)
        else:
            self._set_prec_rel(min(ctx_prec, self.ordp + relprec))
        self._set_from_ZZ_pX_part2(poly)

    cdef int _set_from_ZZ_pX_both(self, ZZ_pX_c* poly, ntl_ZZ_pContext_class ctx, long absprec, long relprec) except -1:
        """
        Sets ``self`` from a ``ZZ_pX`` with relative precision bounded by
        ``relprec`` and absolute precision bounded by ``absprec``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZ_pX([4,1,16],5^2), absprec = 8, relprec = 12); z # indirect doctest
            4 + w + w^2 + 3*w^7 + O(w^8)
            sage: z._ntl_rep()
            [4 1 16]
            sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^50), 220); z
            w^200 + 4*w^207 + 4*w^209 + w^210 + 2*w^211 + 2*w^213 + 2*w^215 + w^217 + 2*w^218 + O(w^220)
            sage: z = W(ntl.ZZ_pX([5^40,5^42,3*5^41], 5^44), absprec = 77); z
            O(w^77)
        """
        cdef long ctx_prec
        if ctx is not None:
            ctx_prec = self._check_ZZ_pContext(ctx)
            if ctx_prec * self.prime_pow.e < absprec:
                absprec = ctx_prec * self.prime_pow.e
        if ZZ_pX_IsZero(poly[0]):
            self._set_inexact_zero(absprec)
            return 0
        self._set_from_ZZ_pX_part1(poly)
        if absprec <= self.ordp:
            self._set_inexact_zero(absprec)
        else:
            self._set_prec_rel(min(absprec, self.ordp + relprec))
            self._set_from_ZZ_pX_part2(poly)

    cdef int _set_from_ZZ_pX_part1(self, ZZ_pX_c* poly) except -1:
        """
        Sets ``self.ordp`` based on ``poly``.  ``poly`` must not be 0.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZ_pX([4,1,16],5^2), absprec = 8, relprec = 12); z # indirect doctest
            4 + w + w^2 + 3*w^7 + O(w^8)
        """
        cdef long val, index
        ZZ_pX_min_val_coeff(val, index, poly[0], self.prime_pow.pow_ZZ_tmp(1)[0])
        if self.prime_pow.e == 1:
            self.ordp = val
        else:
            self.ordp = val * self.prime_pow.e + index

    cdef int _set_from_ZZ_pX_part2(self, ZZ_pX_c* poly) except -1:
        """
        Assuming that ``self.ordp`` and ``self.relprec`` have been set, sets
        ``self.unit`` to ``poly`` and then normalizes.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(ntl.ZZ_pX([4,1,16],5^2), absprec = 8, relprec = 12); z # indirect doctest
            4 + w + w^2 + 3*w^7 + O(w^8)
        """
        # We've set self.relprec to what is actually the absolute precision.
        if self.relprec != 0:
            ZZ_pX_conv_modulus(self.unit, poly[0], self.prime_pow.get_context_capdiv(self.relprec).x)
            self.relprec -= self.ordp
            self._internal_lshift(-self.ordp)

    cdef bint _set_prec_rel(self, long relprec) except -1:
        """
        Safely sets the relative precision of ``self`` to be the absolute
        value of ``relprec``.

        Returns ``True`` iff ``self.relprec`` was reset.

        Note that this will wipe out anything in ``self.unit``.  Be
        careful resetting ``self.unit`` directly: if you set it to a
        different modulus, NTL may have problems.  The safest way to
        reset ``self.unit`` to a different modulus is::

            self.prime_pow.restore_context_capdiv(self.relprec)
            cdef ZZ_pX_c tmp = self.unit
            self._set_prec_rel(new_rel_prec)
            ZZ_pX_conv_modulus(self.unit, tmp, self.prime_pow.get_context_capdiv(self.relprec).x)

        You may be able to just set ``self.relprec`` and
        ``ZZ_pX_conv_modulus`` if you're decreasing precision.  I'm
        not sure.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: W(70, relprec = 8) # indirect doctest
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)
        """
        if self.relprec == relprec:
            return False
        if self.relprec != 0:
            ZZ_pX_destruct(&self.unit)
        if relprec != 0:
            self.prime_pow.restore_context_capdiv(relprec)
            ZZ_pX_construct(&self.unit)
        self.relprec = relprec
        return True

    cdef bint _set_prec_both(self, long absprec, long relprec) except -1:
        """
        Assuming ``self.ordp`` is set, sets the relative precision of ``self``
        to the minimum of ``abs(relprec)`` and ``absprec-self.ordp``.

        If ``relprec`` is negative, will set ``self.relprec`` to be negative
        (indicating unnormalized unit)

        Returns`` True`` iff ``self.relprec = 0``, ie ``self`` was set to an
        inexact zero.

        Note that this will wipe out anything in ``self.unit``.  Be
        careful resetting ``self.unit`` directly: if you set it to a
        different modulus, NTL may have problems.  The safest way to
        reset ``self.unit`` to a different modulus is:

            self.prime_pow.restore_context_capdiv(self.relprec)
            cdef ZZ_pX_c tmp = self.unit
            self._set_prec_rel(new_rel_prec)
            ZZ_pX_conv_modulus(self.unit, tmp, self.prime_pow.get_context_capdiv(self.relprec).x)

        You may be able to just set ``self.relprec`` and
        ``ZZ_pX_conv_modulus`` if you're decreasing precision.  I'm
        not sure.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: W(70, 8) # indirect doctest
            4*w^5 + 3*w^7 + O(w^8)
        """
        if self.relprec != 0:
            ZZ_pX_destruct(&self.unit)
        self.relprec = absprec - self.ordp
        cdef long arelprec
        if relprec < 0:
            arelprec = -relprec
        else:
            arelprec = relprec
        if self.relprec <= 0:
            self._set_inexact_zero(absprec)
        else:
            if arelprec < self.relprec:
                self.relprec = arelprec
            if self.relprec != 0:
                self.prime_pow.restore_context_capdiv(self.relprec)
                ZZ_pX_construct(&self.unit)
                if relprec < 0:
                    self.relprec = -self.relprec
        return self.relprec == 0

    cdef int _normalize(self) except -1:
        """
        Normalizes ``self``, adjusting ``self.ordp``, ``self.relprec``, and
        ``self.unit`` so that ``self.unit`` actually represents a unit.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1+w)^5
            sage: y = z - 1
            sage: y._ntl_rep_unnormalized()
            [5 3005 25 3060 5]
            sage: y # indirect doctest
            w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: y._ntl_rep_unnormalized()
            [41 26 152 49 535]
        """
        cdef long minval, mini, shift
        if self.relprec < 0:
            if ZZ_pX_IsZero(self.unit):
                self.ordp -= self.relprec # note that self.relprec < 0
                self.relprec = 0
                ZZ_pX_destruct(&self.unit)
            else:
                ZZ_pX_min_val_coeff(minval, mini, self.unit, self.prime_pow.pow_ZZ_tmp(1)[0])
                if self.prime_pow.e == 1:
                    shift = minval
                else:
                    shift = minval * self.prime_pow.e + mini
                if shift >= -self.relprec:
                    self.ordp -= self.relprec # note that self.relprec < 0
                    self.relprec = 0
                    ZZ_pX_destruct(&self.unit)
                elif shift > 0:
                    self.relprec = -self.relprec - shift
                    self.ordp += shift
                    self._internal_lshift(-shift)
                else:
                    self.relprec = -self.relprec

    def _is_normalized(self):
        """
        Returns whether this element is currently normalized.

        EXAMPLES::

            sage: R.<a> = ZqCR(125); b = 5*a + 4; c = 10*a^2 + 6; d = b + c
            sage: d._is_normalized()
            False
            sage: d
            (2*a^2 + a + 2)*5 + O(5^20)
            sage: d._is_normalized()
            True
        """
        return self.relprec >= 0

    cdef int _internal_lshift(self, long shift) except -1:
        """
        Multiplies ``self.unit`` by ``x^shift``.

        Note that ``self.relprec`` must be set before calling this
        function and should not be 0, and self.unit must be defined to
        precision ``self.relprec - shift``

        This function does not alter ``self.ordp`` even though it WILL
        change the valuation of ``self.unit``

        Also note that if you call this function you should usually
        manually set ``self.relprec = -self.relprec`` since this function
        will usually unnormalize ``self``.

        TESTS::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1+w)^5
            sage: y = z - 1
            sage: y # indirect doctest
            w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
        """
        if self.relprec == 0:
            raise ValueError("p-adic Internal l-shift called with relative precision 0")
        cdef ZZ_pX_c tmpP
        cdef ZZ_pX_Modulus_c* mod
        if self.prime_pow.e == 1:
            if shift > 0:
                ZZ_pX_left_pshift(self.unit, self.unit, self.prime_pow.pow_ZZ_tmp(shift)[0], self.prime_pow.get_context(self.relprec).x)
            else:
                ZZ_pX_right_pshift(self.unit, self.unit, self.prime_pow.pow_ZZ_tmp(-shift)[0], self.prime_pow.get_context(self.relprec).x)
        else:
            if shift > 0:
                self.prime_pow.restore_context_capdiv(self.relprec)
                mod = self.prime_pow.get_modulus_capdiv(self.relprec)
                ZZ_pX_PowerXMod_long_pre(tmpP, shift, mod[0])
                ZZ_pX_MulMod_pre(self.unit, self.unit, tmpP, mod[0])
            elif shift < 0:
                self.prime_pow.eis_shift_capdiv(&self.unit, &self.unit, -shift, self.relprec)

    cdef int _pshift_self(self, long shift) except -1:
        """
        Multiplies ``self`` by ``p^shift``.

        This function assumes that ``self.relprec``, ``self.ordp`` and
        ``self.unit`` are already set (in the case ``self.prime_pow.e
        != 1``), and is more reasonable to call externally than
        ``_internal_lshift``

        EXAMPLES::

            sage: R = Qp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(3/25, relprec = 6); z
            3*w^-10 + 3*w^-8 + 2*w^-6 + O(w^-4)
            sage: z * 25
            3 + O(w^6)
        """
        cdef ZZ_pX_c high_shifter, high_shifter2
        cdef ZZ_pX_Modulus_c *modulus, modulus_up
        cdef ntl_ZZ_pContext_class c
        cdef PowComputer_ZZ_pX_small_Eis sm
        cdef PowComputer_ZZ_pX_big_Eis big
        cdef ntl_ZZ_pX printer
        cdef ZZ_pX_c* high_array
        cdef long i, high_length
        if self.prime_pow.e == 1:
            self.ordp += shift
        else:
            self.ordp += shift * self.prime_pow.e
            if shift < 0:
                shift = -shift
                c = self.prime_pow.get_context_capdiv(self.relprec)
                c.restore_c()
                modulus = self.prime_pow.get_modulus_capdiv(self.relprec)
                if PY_TYPE_CHECK(self.prime_pow, PowComputer_ZZ_pX_big_Eis):
                    high_array = (<PowComputer_ZZ_pX_big_Eis>self.prime_pow).high_shifter
                elif PY_TYPE_CHECK(self.prime_pow, PowComputer_ZZ_pX_small_Eis):
                    high_array = (<PowComputer_ZZ_pX_small_Eis>self.prime_pow).high_shifter
                else:
                    raise TypeError("unrecognized PowComputer type")
                ZZ_pX_conv_modulus(high_shifter, high_array[0], c.x)
                ZZ_pX_InvMod_newton_ram(high_shifter, high_shifter, modulus[0], c.x)
                ZZ_pX_PowerMod_long_pre(high_shifter, high_shifter, shift, modulus[0])
                ZZ_pX_MulMod_pre(self.unit, self.unit, high_shifter, modulus[0])
            elif shift > 0:
                i = 0
                c = self.prime_pow.get_context_capdiv(self.relprec)
                c.restore_c()
                modulus = self.prime_pow.get_modulus_capdiv(self.relprec)
                if PY_TYPE_CHECK(self.prime_pow, PowComputer_ZZ_pX_big_Eis):
                    high_array = (<PowComputer_ZZ_pX_big_Eis>self.prime_pow).high_shifter
                    high_length = (<PowComputer_ZZ_pX_big_Eis>self.prime_pow).high_length
                elif PY_TYPE_CHECK(self.prime_pow, PowComputer_ZZ_pX_small_Eis):
                    high_array = (<PowComputer_ZZ_pX_small_Eis>self.prime_pow).high_shifter
                    high_length = (<PowComputer_ZZ_pX_small_Eis>self.prime_pow).high_length
                else:
                    raise TypeError("unrecognized PowComputer type")
                if shift >= self.prime_pow.prec_cap:
                    # high_shifter = p^(2^(high_length - 1))/x^(e*2^(high_length - 1))
                    ZZ_pX_conv_modulus(high_shifter, high_array[high_length-1], c.x)
                    # if shift = r + s * 2^(high_length - 1)
                    # then high_shifter = p^(s*2^(high_length - 1))/x^(e*s*2^(high_length - 1))
                    ZZ_pX_PowerMod_long_pre(high_shifter, high_shifter, (shift / (1L << (high_length - 1))), modulus[0])
                    ZZ_pX_MulMod_pre(self.unit, self.unit, high_shifter, modulus[0])
                    # Now we only need to multiply self.unit by p^r/x^(e*r) where r < 2^(high_length - 1), which is tractable.
                    shift = shift % (1L << (high_length - 1))
                while shift > 0:
                    if shift & 1:
                        ZZ_pX_conv_modulus(high_shifter, high_array[i], c.x)
                        ZZ_pX_MulMod_pre(self.unit, self.unit, high_shifter, modulus[0])
                    shift = shift >> 1
                    i += 1

    def __dealloc__(self):
        """
        Deallocates ``self.unit`` if needed.

        EXAMPLES::

            sage: R = Qp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = W(3/25, relprec = 6); z
            3*w^-10 + 3*w^-8 + 2*w^-6 + O(w^-4)
            sage: del z #indirect doctest
        """
        if self.relprec != 0:
            ZZ_pX_destruct(&self.unit)

    cdef pAdicZZpXCRElement _new_c(self, long relprec):
        """
        Returns a new element with the same parent as ``self`` and
        relative precision ``relprec``

        Note that if ``relprec`` is non-positive, the convention is that
        ``relprec = 0`` indicates an exact or inexact zero, ``relprec < 0``
        indicates an unnormalized element.

        EXAMPLES::

            sage: R = Qp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: w^5 + 1 # indirect doctest
            1 + w^5 + O(w^25)
        """
        cdef pAdicZZpXCRElement ans = PY_NEW(pAdicZZpXCRElement)
        ans._parent = self._parent
        ans.prime_pow = self.prime_pow
        if relprec > 0:
            self.prime_pow.restore_context_capdiv(relprec)
            ans.relprec = relprec
            ZZ_pX_construct(&ans.unit)
        elif relprec == 0:
            ans._set_exact_zero()
        else:
            self.prime_pow.restore_context_capdiv(-relprec)
            ans.relprec = relprec
            ZZ_pX_construct(&ans.unit)
        return ans

    def __reduce__(self):
        """
        Pickles ``self``.

        EXAMPLES::

            sage: R = Qp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5 - 1
            sage: loads(dumps(z)) == z
            True
        """
        cdef Integer relprec, ordp
        relprec = PY_NEW(Integer)
        ordp = PY_NEW(Integer)
        mpz_set_si(relprec.value, self.relprec)
        mpz_set_si(ordp.value, self.ordp)
        if self.relprec == 0:
            return make_ZZpXCRElement, (self.parent(), None, ordp, relprec, 0)
        self.prime_pow.restore_context_capdiv(self.relprec)
        cdef ntl_ZZ_pX holder = PY_NEW(ntl_ZZ_pX)
        holder.c = self.prime_pow.get_context_capdiv(self.relprec)
        holder.x = self.unit
        return make_ZZpXCRElement, (self.parent(), holder, ordp, relprec, 0)

    cdef int _cmp_units(left, pAdicGenericElement right) except -2:
        """
        For units ``left`` and ``right``, returns 0 if they are equal up to
        the lesser of the two precisions, or 1 if they are not.

        EXAMPLES::

            sage: R = Qp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: w == 1 # indirect doctest
            False
            sage: y = 1 + w + O(w^7)
            sage: z = 1 + w + w^10 + O(w^13)
            sage: y == z
            True
        """
        # This function needs improvement.  In particular, there are a lot of
        # speed improvements to be had, and it should be changed so that it
        # returns 1 only half the time (and -1 the other half) when left and
        # right are not equal.
        cdef pAdicZZpXCRElement diff = <pAdicZZpXCRElement> (left - right)
        diff._normalize()
        if diff.relprec == 0:
            return 0
        # for now, just return 1
        return 1

    def __invert__(self):
        """
        Returns the inverse of ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5
            sage: y = ~z; y # indirect doctest
            1 + 4*w^5 + 4*w^6 + 3*w^7 + w^8 + 2*w^10 + w^11 + w^12 + 2*w^14 + 3*w^16 + 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24 + O(w^25)
            sage: y.parent()
            Eisenstein Extension of 5-adic Field with capped relative precision 5 in w defined by (1 + O(5^5))*x^5 + (O(5^6))*x^4 + (3*5^2 + O(5^6))*x^3 + (2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))*x^2 + (5^3 + O(5^6))*x + (4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))
            sage: z = z - 1
            sage: ~z
            w^-5 + 4*w^-4 + 4*w^-3 + 4*w^-2 + 2*w^-1 + 1 + w + 4*w^2 + 4*w^3 + 4*w^4 + w^5 + w^6 + w^7 + 4*w^8 + 4*w^9 + 2*w^10 + w^11 + 2*w^12 + 4*w^13 + 4*w^14 + O(w^15)
        """
        return self._invert_c_impl()

    cpdef RingElement _invert_c_impl(self):
        """
        Returns the inverse of ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5
            sage: y = ~z; y # indirect doctest
            1 + 4*w^5 + 4*w^6 + 3*w^7 + w^8 + 2*w^10 + w^11 + w^12 + 2*w^14 + 3*w^16 + 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24 + O(w^25)
            sage: y.parent()
            Eisenstein Extension of 5-adic Field with capped relative precision 5 in w defined by (1 + O(5^5))*x^5 + (O(5^6))*x^4 + (3*5^2 + O(5^6))*x^3 + (2*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))*x^2 + (5^3 + O(5^6))*x + (4*5 + 4*5^2 + 4*5^3 + 4*5^4 + 4*5^5 + O(5^6))
            sage: z = z - 1
            sage: ~z
            w^-5 + 4*w^-4 + 4*w^-3 + 4*w^-2 + 2*w^-1 + 1 + w + 4*w^2 + 4*w^3 + 4*w^4 + w^5 + w^6 + w^7 + 4*w^8 + 4*w^9 + 2*w^10 + w^11 + 2*w^12 + 4*w^13 + 4*w^14 + O(w^15)
            sage: ~z * z
            1 + O(w^20)
        """
        if self._is_exact_zero():
            raise ZeroDivisionError, "cannot divide by zero"
        if self._is_inexact_zero(): # this calls _normalize
            raise PrecisionError, "cannot divide by something indistinguishable from zero"
        cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
        if not ans.prime_pow.in_field:
            ans._parent = self._parent.fraction_field()
            ans.prime_pow = ans._parent.prime_pow
        ans.ordp = -self.ordp
        sig_on()
        if self.prime_pow.e == 1:
            ZZ_pX_InvMod_newton_unram(ans.unit, self.unit, self.prime_pow.get_modulus(ans.relprec)[0], self.prime_pow.get_context(ans.relprec).x, self.prime_pow.get_context(1).x)
        else:
            ZZ_pX_InvMod_newton_ram(ans.unit, self.unit, self.prime_pow.get_modulus_capdiv(ans.relprec)[0], self.prime_pow.get_context_capdiv(ans.relprec).x)
        sig_off()
        return ans

    cdef pAdicZZpXCRElement _lshift_c(self, long n):
        """
        Multiplies ``self`` by the uniformizer raised to the power ``n``.  If
        ``n`` is negative, right shifts by ``-n``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5
            sage: z
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: z << 17 # indirect doctest
            w^17 + w^22 + w^23 + 2*w^24 + 4*w^25 + 3*w^27 + w^29 + 4*w^30 + 4*w^31 + 4*w^32 + 4*w^33 + 4*w^34 + 4*w^37 + w^38 + 4*w^41 + O(w^42)
            sage: z << (-1)
            w^4 + w^5 + 2*w^6 + 4*w^7 + 3*w^9 + w^11 + 4*w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^19 + w^20 + 4*w^23 + O(w^24)
        """
        if not self.prime_pow.in_field and n < -self.ordp:
            return self._rshift_c(-n)
        check_ordp(n)
        cdef pAdicZZpXCRElement ans
        if self._is_exact_zero() or n == 0:
            return self
        elif self._is_inexact_zero():
            ans = self._new_c(0)
        else:
            ans = self._new_c(self.relprec)
            ans.unit = self.unit
        ans.ordp = self.ordp + n
        check_ordp(ans.ordp)
        return ans

    def __lshift__(pAdicZZpXCRElement self, shift):
        """
        Multiplies ``self`` by the uniformizer raised to the power ``n``.  If
        ``n`` is negative, right shifts by ``-n``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5
            sage: z
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: z << 17 # indirect doctest
            w^17 + w^22 + w^23 + 2*w^24 + 4*w^25 + 3*w^27 + w^29 + 4*w^30 + 4*w^31 + 4*w^32 + 4*w^33 + 4*w^34 + 4*w^37 + w^38 + 4*w^41 + O(w^42)
            sage: z << (-1)
            w^4 + w^5 + 2*w^6 + 4*w^7 + 3*w^9 + w^11 + 4*w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^19 + w^20 + 4*w^23 + O(w^24)
        """
        cdef pAdicZZpXCRElement ans
        if not PY_TYPE_CHECK(shift, Integer):
            shift = Integer(shift)
        if mpz_fits_slong_p((<Integer>shift).value) == 0:
            if self._is_exact_zero():
                return self
            if self.prime_pow.in_field or mpz_sgn((<Integer>shift).value) > 0:
                raise ValueError, "Shift does not fit in long"
            else:
                ans = self._new_c(0)
                ans.ordp = 0
                return ans
        return self._lshift_c(mpz_get_si((<Integer>shift).value))

    cdef pAdicZZpXCRElement _rshift_c(self, long n):
        """
        Divides self by the uniformizer raised to the power ``n``.  If
        parent is not a field, throws away the non-positive part of
        the series expansion.  If ``n`` is negative, left shifts by ``-n``.

        EXAMPLES::

            sage: R = Zp(5,5,print_mode='digits')
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5
            sage: for m in range(26): repr(z >> m) # indirect doctest
            '...4001400444441030421100001'
            '...400140044444103042110000'
            '...40014004444410304211000'
            '...4001400444441030421100'
            '...400140044444103042110'
            '...40014004444410304211'
            '...4001400444441030421'
            '...400140044444103042'
            '...40014004444410304'
            '...4001400444441030'
            '...400140044444103'
            '...40014004444410'
            '...4001400444441'
            '...400140044444'
            '...40014004444'
            '...4001400444'
            '...400140044'
            '...40014004'
            '...4001400'
            '...400140'
            '...40014'
            '...4001'
            '...400'
            '...40'
            '...4'
            '...'
            sage: repr(z >> (-4))
            '...40014004444410304211000010000'
        """
        if self.prime_pow.in_field or n <= self.ordp:
            return self._lshift_c(-n)
        if self._is_exact_zero() or n == 0:
            return self
        cdef long arelprec
        if self.relprec < 0:
            arelprec = -self.relprec
        else:
            arelprec = self.relprec
        cdef pAdicZZpXCRElement ans
        if arelprec > n - self.ordp:
            ans = self._new_c(arelprec - (n - self.ordp))
            if self.prime_pow.e == 1:
                ZZ_pX_right_pshift(ans.unit, self.unit, self.prime_pow.pow_ZZ_tmp(n - self.ordp)[0], self.prime_pow.get_context(ans.relprec).x)
            else:
                self.prime_pow.eis_shift_capdiv(&ans.unit, &self.unit, n - self.ordp, ans.relprec)
        else:
            ans = self._new_c(0)
        ans.ordp = 0
        ans.relprec = -ans.relprec
        return ans

    def __rshift__(pAdicZZpXCRElement self, shift):
        """
        Divides self by the uniformizer raised to the power ``n``.  If
        parent is not a field, throws away the non-positive part of
        the series expansion.  If ``n`` is negative, left shifts by ``-n``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5
            sage: z
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: z >> (6) # indirect doctest
            1 + 2*w + 4*w^2 + 3*w^4 + w^6 + 4*w^7 + 4*w^8 + 4*w^9 + 4*w^10 + 4*w^11 + 4*w^14 + w^15 + 4*w^18 + O(w^19)
            sage: z >> (-4)
            w^4 + w^9 + w^10 + 2*w^11 + 4*w^12 + 3*w^14 + w^16 + 4*w^17 + 4*w^18 + 4*w^19 + 4*w^20 + 4*w^21 + 4*w^24 + w^25 + 4*w^28 + O(w^29)
            sage: F = W.fraction_field()
            sage: z = F(z)
            sage: z >> 7
            w^-7 + w^-2 + w^-1 + 2 + 4*w + 3*w^3 + w^5 + 4*w^6 + 4*w^7 + 4*w^8 + 4*w^9 + 4*w^10 + 4*w^13 + w^14 + 4*w^17 + O(w^18)
        """
        cdef pAdicZZpXCRElement ans
        if not PY_TYPE_CHECK(shift, Integer):
            shift = Integer(shift)
        if mpz_fits_slong_p((<Integer>shift).value) == 0:
            if self._is_exact_zero():
                return self
            if self.prime_pow.in_field or mpz_sgn((<Integer>shift).value) < 0:
                raise ValueError, "valuation overflow"
            else:
                ans = self._new_c(0)
                ans.ordp = 0
                return ans
        return self._rshift_c(mpz_get_si((<Integer>shift).value))

    cpdef ModuleElement _neg_(self):
        """
        Returns ``-self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: z = (1 + w)^5; z
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: -z # indirect doctest
            4 + 3*w^5 + 4*w^6 + w^7 + w^8 + w^9 + w^10 + w^11 + 2*w^12 + 4*w^13 + 4*w^15 + 3*w^16 + w^17 + 2*w^18 + 3*w^19 + 2*w^21 + 4*w^23 + 4*w^24 + O(w^25)
            sage: y = z + (-z); y
            O(w^25)
            sage: -y
            O(w^25)
            sage: -W(0)
            0
        """
        cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
        ans.ordp = self.ordp
        if self.relprec != 0:
            self.prime_pow.restore_context_capdiv(self.relprec)
            ZZ_pX_negate(ans.unit, self.unit)
        return ans

#                                             / 1 + \alpha^p \pi_K^{p \lambda}                      mod \mathfrak{p}_K^{p \lambda + 1}   if 1 \le \lambda < \frac{e_K}{p-1}
#        (1 + \alpha \pi^{\lambda})^p \equiv {  1 + (\alpha^p - \epsilon \alpha) \pi_K^{p \lambda}  mod \mathfrak{p}_K^{p \lambda + 1}   if \lambda = \frac{e_K}{p-1}
#                                             \ 1 - \epsilon \alpha \pi_K^{\lambda + e}             mod \mathfrak{p}_K^{\lambda + e + 1} if \lambda > \frac{e_K}{p-1}


    def __pow__(pAdicZZpXCRElement self, _right, m): # m ignored
        r"""
        Computes ``self^right``.

        Note: when ``right`` is divisible by `p` then one can get more
        precision than expected.

        Lemma 2.1 (Constructing Class Fields over Local Fields, Sebastian Pauli):

        Let `\alpha` be in `\mathcal{O}_K`.  Let

        ..math ::

            p = -\pi_K^{e_K} \epsilon

        be the factorization of `p` where `\epsilon` is a unit.  Then
        the `p`-th power of `1 + \alpha \pi_K^{\lambda}` satisfies

        ..math ::

            (1 + \alpha \pi^{\lambda})^p \equiv \left{ \begin{array}{lll}
            1 + \alpha^p \pi_K^{p \lambda} & \mod \mathfrak{p}_K^{p \lambda + 1} & \mbox{if $1 \le \lambda < \frac{e_K}{p-1}$} \\
            1 + (\alpha^p - \epsilon \alpha) \pi_K^{p \lambda} & \mod \mathfrak{p}_K^{p \lambda + 1} & \mbox{if $\lambda = \frac{e_K}{p-1}$} \\
            1 - \epsilon \alpha \pi_K^{\lambda + e} & \mod \mathfrak{p}_K^{\lambda + e + 1} & \mbox{if $\lambda > \frac{e_K}{p-1}$}
            \end{array} \right.


        So if ``right`` is divisible by `p^k` we can multiply the
        relative precision by `p` until we exceed `e/(p-1)`, then add
        `e` until we have done a total of `k` things: the precision of
        the result can therefore be greater than the precision of
        ``self``.

        There is also the issue of `p`-adic exponents, and determining
        how the precision of the exponent affects the precision of the
        result.

        In computing `(a + O(\pi^k))^{b + O(p^m)}`, one needs that the
        reduction of `a` mod `\pi` is in the prime field
        `\mathbb{F}_p` (so that the `p^m` power of the Teichmuller
        part is constant as `m` increases).  Given this restriction,
        we can factor out the Teichmuller part and use the above lemma
        to find the first spot where

        ..math::

            (1 + \alpha \pi^{\lambda})^{p^m}

        differs from 1.  We compare this with the precision bound
        given by computing `(a + O(\pi^k))^b` and take the lesser of
        the two.

        In order to do this we need to compute the valuation of ``(self
        / self.parent().teichmuller(self)) - 1``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: (1 + w)^5 # indirect doctest
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + 4*w^24 + O(w^25)
            sage: (1 + w)^-5
            1 + 4*w^5 + 4*w^6 + 3*w^7 + w^8 + 2*w^10 + w^11 + w^12 + 2*w^14 + 3*w^16 + 3*w^17 + 4*w^18 + 4*w^19 + 2*w^20 + 2*w^21 + 4*w^22 + 3*w^23 + 3*w^24 + O(w^25)
            sage: (1 + w + O(w^19))^5
            1 + w^5 + w^6 + 2*w^7 + 4*w^8 + 3*w^10 + w^12 + 4*w^13 + 4*w^14 + 4*w^15 + 4*w^16 + 4*w^17 + 4*w^20 + w^21 + O(w^24)
            sage: (1 + O(w))^5
            1 + O(w^5)
            sage: (1 + w + O(w^3))^25
            1 + w^10 + w^11 + 4*w^12 + O(w^13)
            sage: (3 + 2*w + w^2 + O(w^6))^(15 + O(125))
            2 + 4*w^6 + w^7 + 3*w^8 + 3*w^9 + 4*w^10 + O(w^11)
            sage: (3 + 2*w + w^2 + O(w^6))^(15 + O(25))
            2 + 4*w^6 + w^7 + 3*w^8 + 3*w^9 + O(w^10)
            sage: (3 + w^2 + O(w^6))^(15+O(25))
            2 + w^5 + 4*w^7 + w^9 + 3*w^10 + O(w^11)
            sage: R = Zp(2, 10)
            sage: S.<x> = R[]
            sage: f = x^34 + 18*x^5 - 72*x^3 + 2
            sage: W.<w> = R.ext(f)
            sage: (1+w+O(w^2))^8
            1 + w^8 + O(w^16)
            sage: (1+w+O(w^2))^16
            1 + w^16 + O(w^32)
            sage: (1+w+O(w^2))^32
            1 + w^32 + w^50 + w^55 + w^60 + O(w^64)
            sage: (1+w+O(w^2))^64
            1 + w^64 + w^66 + w^71 + w^76 + w^81 + w^84 + w^86 + w^91 + w^94 + w^96 + O(w^98)

        TESTS:

            We define ``0^0`` to be unity, :trac:`13786`::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: type(W(0))
            <type 'sage.rings.padics.padic_ZZ_pX_CR_element.pAdicZZpXCRElement'>
            sage: W(0)^0
            1 + O(w^25)
            sage: W(0)^0 == W(1)
            True

        The value returned from ``0^0`` should belong to our ring::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: type(W(0)^0) == type(W(0))
            True

        """
        self._normalize()
        cdef Integer right
        cdef bint padic_exp
        cdef long exp_prec
        cdef long exp_val
        cdef long relprec
        cdef long threshold # e / (p-1)
        cdef long prime_long
        cdef mpz_t tmp, tmp2
        if mpz_fits_slong_p(self.prime_pow.prime.value) == 0:
            threshold = 0
        else:
            threshold = self.prime_pow.e / (mpz_get_si(self.prime_pow.prime.value) - 1)
        cdef Integer base_level
        cdef pAdicZZpXCRElement ans
        cdef long i
        if self._is_exact_zero():
            # Return 0 except for 0^0 error or type error on the exponent.
            if PY_TYPE_CHECK(_right, Integer) or PY_TYPE_CHECK(_right, Rational) or (PY_TYPE_CHECK(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime))  or isinstance(_right, (int, long)):
                if _right == 0:
                    return self.parent(1)
                return self
            else:
                raise TypeError, "exponent must be an integer, rational or base p-adic with the same prime"
        elif self._is_inexact_zero():
            # If an integer exponent, return an inexact zero of valuation right * self.ordp.  Otherwise raise an error.
            if isinstance(_right, (int, long)):
                _right = Integer(_right)
            if PY_TYPE_CHECK(_right, Integer):
                ans = self._new_c(0)
                mpz_init_set_si(tmp, self.ordp)
                mpz_mul(tmp, tmp, (<Integer>_right).value)
                if mpz_cmp_si(tmp, maxordp) >= 0 or mpz_cmp_si(tmp, -maxordp) <= 0:
                    raise ValueError, "valuation overflow"
                ans.ordp = mpz_get_si(tmp)
                mpz_clear(tmp)
                return ans
            elif PY_TYPE_CHECK(_right, Rational) or (PY_TYPE_CHECK(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime)):
                raise ValueError, "Need more precision"
            else:
                raise TypeError, "exponent must be an integer, rational or base p-adic with the same prime"
        if isinstance(_right, (int, long)):
            _right = Integer(_right)
        if PY_TYPE_CHECK(_right, Integer):
            right = <Integer> _right
            if right == 0:
                # return 1 to maximum precision
                ans = self._new_c(self.prime_pow.ram_prec_cap)
                ans.ordp = 0
                ZZ_pX_SetCoeff_long(ans.unit, 0, 1)
                return ans
            padic_exp = False
            exp_val = _right.valuation(self.prime_pow.prime) ##
        elif PY_TYPE_CHECK(_right, pAdicGenericElement) and _right._is_base_elt(self.prime_pow.prime):
            if self.ordp != 0:
                raise ValueError, "in order to raise to a p-adic exponent, base must be a unit"
            right = Integer(_right)
            padic_exp = True
            exp_prec = _right.precision_absolute() ##
            exp_val = _right.valuation() ##
            if exp_val < 0:
                raise NotImplementedError, "negative valuation exponents not yet supported"
            # checks to see if the residue of self.unit is in the prime field.
            if self.prime_pow.e == 1:
                for i from 1 <= i <= ZZ_pX_deg(self.unit):
                    if not ZZ_divide_test(ZZ_p_rep(ZZ_pX_coeff(self.unit, i)), self.prime_pow.pow_ZZ_tmp(1)[0]):
                        raise ValueError, "in order to raise to a p-adic exponent, base must reduce to an element of F_p mod the uniformizer"
            # compute the "level"
            teich_part = self.parent().teichmuller(self)
            base_level = (self / teich_part - 1).valuation() ##
        elif PY_TYPE_CHECK(_right, Rational):
            raise NotImplementedError
        else:
            raise TypeError, "exponent must be an integer, rational or base p-adic with the same prime"
        # Now we compute the increased relprec due to the exponent having positive p-adic valuation
        if exp_val > 0:
            mpz_init_set_si(tmp, self.relprec)
            while mpz_cmp_si(tmp, threshold) <= 0 and exp_val > 0:
                mpz_mul(tmp, tmp, self.prime_pow.prime.value)
                exp_val -= 1
            if exp_val > 0:
                mpz_init_set_si(tmp2, self.prime_pow.e)
                mpz_addmul_ui(tmp, tmp2, exp_val)
                mpz_clear(tmp2)
            if mpz_cmp_si(tmp, self.prime_pow.ram_prec_cap) > 0:
                relprec = self.prime_pow.ram_prec_cap
            else:
                relprec = mpz_get_si(tmp)
            mpz_clear(tmp)
        else:
            relprec = self.relprec
        # Now we compute the limit on relprec due to a non-infinite precision on the exponent.
        if padic_exp:
            if exp_prec > 0:
                # I can freely change base_level, so I use it in place of tmp above.
                while mpz_cmp_si(base_level.value, threshold) <= 0 and exp_prec > 0:
                    mpz_mul(base_level.value, base_level.value, self.prime_pow.prime.value)
                    exp_prec -= 1
                if exp_prec > 0:
                    mpz_init_set_si(tmp2, self.prime_pow.e)
                    mpz_addmul_ui(base_level.value, tmp2, exp_prec)
                    mpz_clear(tmp2)
                if mpz_cmp_si(base_level.value, relprec) < 0:
                    relprec = mpz_get_si(base_level.value)
            else:
                ans = self._new_c(0)
                ans.ordp = 0
                return ans
        ans = self._new_c(relprec)
        if self.ordp == 0:
            ans.ordp = 0
        else:
            mpz_init_set(tmp, right.value)
            mpz_mul_si(tmp, tmp, self.ordp)
            if mpz_cmp_si(tmp, maxordp) >= 0 or mpz_cmp_si(tmp, -maxordp) <= 0:
                raise ValueError, "valuation overflow"
            ans.ordp = mpz_get_si(tmp)
            mpz_clear(tmp)
        cdef ntl_ZZ rZZ = PY_NEW(ntl_ZZ)
        mpz_to_ZZ(&rZZ.x, right.value)
        sig_on()
        if mpz_sgn(right.value) < 0:
            if self.prime_pow.e == 1:
                ZZ_pX_InvMod_newton_unram(ans.unit, self.unit, self.prime_pow.get_modulus(ans.relprec)[0], self.prime_pow.get_context(ans.relprec).x, self.prime_pow.get_context(1).x)
            else:
                ZZ_pX_InvMod_newton_ram(ans.unit, self.unit, self.prime_pow.get_modulus_capdiv(ans.relprec)[0], self.prime_pow.get_context_capdiv(ans.relprec).x)
            ZZ_negate(rZZ.x, rZZ.x)
            ZZ_pX_PowerMod_pre(ans.unit, ans.unit, rZZ.x, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
        else:
            ZZ_pX_PowerMod_pre(ans.unit, self.unit, rZZ.x, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
        sig_off()
        return ans

    cpdef ModuleElement _add_(self, ModuleElement _right):
        """
        Computes the sum of ``self`` and ``right``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)) - 69 # indirect doctest
            1 + O(w^13)
            sage: -69 + (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13))
            1 + O(w^13)
            sage: y = (4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13))
            sage: y - 70
            O(w^13)
            sage: y + 0
            4*w^5 + 3*w^7 + w^9 + 2*w^10 + 2*w^11 + O(w^13)
        """
        cdef pAdicZZpXCRElement right = <pAdicZZpXCRElement>_right
        cdef pAdicZZpXCRElement ans
        cdef long tmpL
        cdef ZZ_pX_c tmpP
        if self.relprec == 0:
            if self.ordp >= right.ordp + right.relprec: # or self._is_exact_zero()
                return right
            elif self.ordp <= right.ordp:
                ans = self._new_c(0)
                ans.ordp = self.ordp
            else:
                ans = self._new_c(self.ordp - right.ordp)
                ZZ_pX_conv_modulus(ans.unit, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
                if right.relprec < 0:
                    ans.relprec = -ans.relprec
                ans.ordp = right.ordp
            return ans
        if right.relprec == 0:
            if right.ordp >= self.ordp + self.relprec: # or right._is_exact_zero()
                return self
            elif right.ordp <= self.ordp:
                ans = self._new_c(0)
                ans.ordp = right.ordp
            else:
                ans = self._new_c(right.ordp - self.ordp)
                ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
                if self.relprec < 0:
                    ans.relprec = -ans.relprec
                ans.ordp = self.ordp
            return ans
        cdef long srprec = self.relprec
        if srprec < 0:
            srprec = -srprec
        cdef long rrprec = right.relprec
        if rrprec < 0:
            rrprec = -rrprec
        #print "self.ordp = %s\nright.ordp = %s"%(self.ordp, right.ordp)
        #print "self = %s\nright = %s"%(self, right)
        if self.ordp == right.ordp:
            # The relative precision of the sum is the minimum of the relative precisions in this case, possibly decreasing if we got cancellation
            # Since the valuations are the same, we could just add the units, if they had the same modulus.
            # But they don't necessarily, so we may have to conv_modulus
            if srprec == rrprec:
                ans = self._new_c(-srprec) # -srprec indicates that ans is not normalized
                self.prime_pow.restore_context_capdiv(srprec)
                ZZ_pX_add(ans.unit, self.unit, right.unit)
            elif srprec < rrprec:
                ans = self._new_c(-srprec)
                ZZ_pX_conv_modulus(ans.unit, right.unit, self.prime_pow.get_context_capdiv(srprec).x)
                self.prime_pow.restore_context_capdiv(srprec)
                # conv_modulus should have restored the context, so we don't need to again.
                ZZ_pX_add(ans.unit, ans.unit, self.unit)
            else:
                ans = self._new_c(-rrprec)
                ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(rrprec).x)
                self.prime_pow.restore_context_capdiv(rrprec)
                # conv_modulus should have restored the context, so we don't need to again.
                ZZ_pX_add(ans.unit, ans.unit, right.unit)
            ans.ordp = self.ordp
        elif self.ordp < right.ordp:
            tmpL = right.ordp - self.ordp
            if tmpL >= srprec:
                return self
            if srprec <= tmpL + rrprec:
                ans = self._new_c(-srprec)
            else:
                ans = self._new_c(-tmpL - rrprec)
            ans.ordp = self.ordp
            ZZ_pX_conv_modulus(ans.unit, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
            ans._internal_lshift(tmpL)
            if srprec <= tmpL + rrprec:
                ZZ_pX_add(ans.unit, ans.unit, self.unit)
            else:
                ZZ_pX_conv_modulus(tmpP, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
                ZZ_pX_add(ans.unit, ans.unit, tmpP)
            # if self is normalized, then the valuations are actually different so the sum will be normalized.
            if self.relprec > 0:
                ans.relprec = -ans.relprec
        else:
            tmpL = self.ordp - right.ordp
            if tmpL >= rrprec:
                return right
            if rrprec <= tmpL + srprec:
                ans = self._new_c(-rrprec)
            else:
                ans = self._new_c(-tmpL - srprec)
            ans.ordp = right.ordp
            ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
            ans._internal_lshift(tmpL)
            if rrprec <= tmpL + srprec:
                ZZ_pX_add(ans.unit, ans.unit, right.unit)
            else:
                ZZ_pX_conv_modulus(tmpP, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
                ZZ_pX_add(ans.unit, ans.unit, tmpP)
            # if right is normalized, then the valuations are actually different so the sum will be normalized.
            if right.relprec > 0:
                ans.relprec = -ans.relprec
        return ans

    cpdef ModuleElement _sub_(self, ModuleElement right):
        """
        Returns the difference of ``self`` and ``right``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(329)
            sage: b = W(111)
            sage: a - b #indirect doctest
            3 + 3*w^5 + w^7 + 2*w^9 + 3*w^10 + 4*w^11 + 2*w^13 + 2*w^14 + w^15 + 4*w^16 + 2*w^18 + 3*w^19 + 2*w^20 + 3*w^21 + w^22 + w^24 + O(w^25)
            sage: W(218)
            3 + 3*w^5 + w^7 + 2*w^9 + 3*w^10 + 4*w^11 + 2*w^13 + 2*w^14 + w^15 + 4*w^16 + 2*w^18 + 3*w^19 + 2*w^20 + 3*w^21 + w^22 + w^24 + O(w^25)
            sage: a - O(w^14)
            4 + 3*w^10 + 2*w^12 + O(w^14)
            sage: a - 0
            4 + 3*w^10 + 2*w^12 + w^14 + 2*w^15 + w^16 + 3*w^17 + 3*w^18 + w^19 + 2*w^21 + 4*w^22 + w^23 + 4*w^24 + O(w^25)
            sage: O(w^14) - a
            1 + 4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + O(w^14)
        """
        # For now, a simple implementation
        return self + (-right)

    cpdef RingElement _mul_(self, RingElement _right):
        """
        Returns the product of ``self`` and ``right``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(329)
            sage: b = W(111)
            sage: a*b #indirect doctest
            4 + 3*w^5 + w^7 + 2*w^9 + 4*w^11 + 3*w^12 + 2*w^13 + w^14 + 2*w^15 + 3*w^16 + 4*w^17 + 4*w^18 + 2*w^19 + 2*w^21 + 4*w^22 + 2*w^23 + w^24 + O(w^25)
            sage: a * 0
            0
            sage: a * O(w^14)
            O(w^14)
        """
        cdef pAdicZZpXCRElement right = <pAdicZZpXCRElement>_right
        cdef ZZ_pX_c modulus_corrected
        cdef ntl_ZZ_pContext_class ctx
        cdef pAdicZZpXCRElement ans
        if self._is_exact_zero():
            return self
        if right._is_exact_zero():
            return right
        self._normalize()
        right._normalize()
        if self.relprec <= right.relprec:
            ans = self._new_c(self.relprec)
        else:
            ans = self._new_c(right.relprec)
        ans.ordp = self.ordp + right.ordp
        check_ordp(ans.ordp)
        if ans.relprec == 0:
            return ans
        if self.relprec == right.relprec:
            self.prime_pow.restore_context_capdiv(ans.relprec)
            sig_on()
            ZZ_pX_MulMod_pre(ans.unit, self.unit, right.unit, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
            sig_off()
        elif self.relprec < right.relprec:
            sig_on()
            ZZ_pX_conv_modulus(modulus_corrected, right.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
            ZZ_pX_MulMod_pre(ans.unit, self.unit, modulus_corrected, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
            sig_off()
        else:
            sig_on()
            ZZ_pX_conv_modulus(modulus_corrected, self.unit, self.prime_pow.get_context_capdiv(ans.relprec).x)
            ZZ_pX_MulMod_pre(ans.unit, right.unit, modulus_corrected, self.prime_pow.get_modulus_capdiv(ans.relprec)[0])
            sig_off()
        return ans

    cpdef RingElement _div_(self, RingElement right):
        """
        Returns the quotient of ``self`` by ``right``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: W(14) / W(125) #indirect doctest
            4*w^-15 + w^-13 + 3*w^-11 + 2*w^-10 + 3*w^-9 + 4*w^-8 + 4*w^-7 + 3*w^-6 + 2*w^-5 + 4*w^-4 + 3*w^-3 + 2*w^-2 + 4*w^-1 + 2 + w^2 + w^4 + 4*w^5 + w^6 + w^7 + 3*w^9 + O(w^10)
            sage: 1 / w
            w^-1 + O(w^24)
            sage: W.<w> = R.ext(x^25 - 165*x + 5)
            sage: a = (1 + w)^25 - 1
            sage: b = (1 + w)^5 - 1
            sage: c = (1 + w)^20 + (1 + w)^15 + (1 + w)^10 + (1 + w)^5 + 1
            sage: d = a / b; d == c
            True
            sage: d.precision_absolute()
            120
            sage: c.precision_absolute()
            125
            sage: 1 / a == ~a
            True
        """
        # for now, a simple implementation
        return self * (~right)

    def __copy__(self):
        """
        Returns a copy of ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: b = W(45, 17); b
            4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + 3*w^14 + w^16 + O(w^17)
            sage: c = copy(b); c
            4*w^5 + 3*w^7 + w^9 + w^10 + 2*w^11 + w^12 + w^13 + 3*w^14 + w^16 + O(w^17)
            sage: c is b
            False
        """
        cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
        ans.ordp = self.ordp
        ans.unit = self.unit
        return ans

    def _integer_(self, Z=None):
        """
        Returns an integer congruent to this element modulo
        `\pi`^``self.absolute_precision()``, if possible.

        EXAMPLES::

            sage: ZZ(ZqCR(125,names='a')(-1)) #indirect doctest
            95367431640624
            sage: R = Zp(5); S.<x> = ZZ[]; f = x^5 + 25*x^3 - 5; W.<w> = R.ext(f)
            sage: ZZ(W(-1))
            95367431640624
            sage: ZZ(W(0))
            0
            sage: ZZ(W(0,7))
            0
            sage: ZZ(w)
            Traceback (most recent call last):
            ...
            ValueError: This element not well approximated by an integer.
            sage: ZZ(W(5)) # todo: this should be different...
            381469726562505
        """
        cdef Integer ans
        cdef ZZ_c tmp_z
        if self._is_exact_zero() or self.relprec == 0:
            ans = PY_NEW(Integer)
            return ans
        if self.ordp < 0:
            self._normalize()
            if self.ordp < 0:
                raise ValueError, "This element has negative valuation"
        cdef ntl_ZZ_pX f = <ntl_ZZ_pX>self._ntl_rep_abs()[0]
        if f.degree() > 0:
            raise ValueError, "This element not well approximated by an integer."
        ans = PY_NEW(Integer)
        tmp_z = ZZ_p_rep(ZZ_pX_ConstTerm(f.x))
        ZZ_to_mpz(ans.value, &tmp_z)
        return ans

    def is_zero(self, absprec = None):
        """
        Returns whether the valuation of ``self`` is at least
        ``absprec``.  If ``absprec`` is ``None``, returns if ``self``
        is indistinguishable from zero.

        If ``self`` is an inexact zero of valuation less than ``absprec``,
        raises a PrecisionError.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: O(w^189).is_zero()
            True
            sage: W(0).is_zero()
            True
            sage: a = W(675)
            sage: a.is_zero()
            False
            sage: a.is_zero(7)
            True
            sage: a.is_zero(21)
            False
        """
        cdef bint ans
        cdef long aprec
        self._normalize()
        if self._is_exact_zero():
            ans = True
        elif absprec is None:
            ans = (self.relprec == 0)
        else:
            if not PY_TYPE_CHECK(absprec, Integer):
                absprec = Integer(absprec)
            if mpz_fits_slong_p((<Integer>absprec).value) == 0:
                if mpz_sgn((<Integer>absprec).value) < 0:
                    ans = True
                elif self.relprec == 0:
                    raise PrecisionError, "Not enough precision to determine if element is zero"
                else:
                    ans = False
            else:
                aprec = mpz_get_si((<Integer>absprec).value)
                if self.relprec == 0 and aprec > self.ordp:
                    raise PrecisionError, "Not enough precision to determine if element is zero"
                else:
                    ans = (self.ordp >= aprec)
        return ans

    cpdef ntl_ZZ_pX _ntl_rep_unnormalized(self):
        """
        Returns an ``ntl_ZZ_pX`` holding the current unit part of ``self``.

        ``self`` is not normalized before this, so the polynomial
        returned may not actually be a unit.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(566); b = W(209)
            sage: c = a + b; c._ntl_rep_unnormalized()
            [775]
            sage: c
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24 + O(w^25)
            sage: c._ntl_rep_unnormalized()
            [106 60 114 35 112]
        """
        if self.relprec == 0:
            raise ValueError, "self == 0"
        self.prime_pow.restore_context_capdiv(self.relprec)
        cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX)
        ans.c = self.prime_pow.get_context_capdiv(self.relprec)
        ans.x = self.unit
        return ans

    cpdef ntl_ZZ_pX _ntl_rep(self):
        """
        Returns an ``ntl_ZZ_pX`` that holds the unit part of ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(566); b = W(209)
            sage: c = a + b; c._ntl_rep()
            [106 60 114 35 112]
            sage: c
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24 + O(w^25)
            sage: c._ntl_rep()
            [106 60 114 35 112]
        """
        self._normalize()
        return self._ntl_rep_unnormalized()

    cpdef _ntl_rep_abs(self):
        """
        Returns a pair ``(f, k)`` where ``f`` is an ``ntl_ZZ_pX`` and ``k`` is a
        non-positive integer such that ``self = f(self.parent.gen())*p^k``

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(566); b = W(209)
            sage: c = a + b; c._ntl_rep_abs()
            ([775], 0)
            sage: c
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + w^20 + 2*w^21 + 3*w^22 + w^23 + w^24 + O(w^25)
            sage: c._ntl_rep_abs()
            ([775], 0)
            sage: (~c)._ntl_rep_abs()
            ([121], -2)
            sage: ~c
            w^-10 + w^-8 + 4*w^-6 + 4*w^-5 + 3*w^-3 + 4*w^-2 + 3*w^-1 + 4 + 4*w + 2*w^2 + 4*w^3 + 3*w^4 + O(w^5)
            sage: ~c * 25
            1 + 4*w^5 + 3*w^7 + w^9 + 4*w^10 + 2*w^11 + 3*w^12 + w^13 + 4*w^14 + O(w^15)
            sage: W(121)
            1 + 4*w^5 + 3*w^7 + w^9 + 4*w^10 + 2*w^11 + 3*w^12 + w^13 + 4*w^14 + 2*w^16 + 3*w^17 + 3*w^18 + 4*w^19 + 4*w^20 + 3*w^21 + w^22 + w^23 + 4*w^24 + O(w^25)
        """
        self._normalize()
        if self.ordp == 0:
            return self._ntl_rep(), Integer(0)
        cdef ntl_ZZ_pContext_class ctx
        cdef long little_shift, ppow
        if self.ordp > 0:
            ctx = self.prime_pow.get_context_capdiv(self.ordp + self.relprec)
        else:
            little_shift = ((-self.ordp) % self.prime_pow.e)
            if little_shift != 0:
                little_shift = self.prime_pow.e - little_shift
            ctx = self.prime_pow.get_context_capdiv(self.relprec + little_shift)
        ctx.restore_c()
        cdef pAdicZZpXCRElement dummy = PY_NEW(pAdicZZpXCRElement)
        cdef ntl_ZZ_pX ans = PY_NEW(ntl_ZZ_pX)
        cdef Integer ans_k = PY_NEW(Integer)
        dummy.unit = self.unit
        dummy.prime_pow = self.prime_pow
        if self.ordp > 0:
            dummy.relprec = self.ordp + self.relprec
            dummy._internal_lshift(self.ordp)
            ans.x = dummy.unit
        else:
            ppow = (self.ordp - little_shift) / self.prime_pow.e
            mpz_set_si(ans_k.value, ppow)
            dummy.ordp = 0 # _pshift_self wants ordp set
            dummy.relprec = self.relprec + little_shift
            # self = x^(self.prime_pow.e * ppow) * x^(little_shift) * self.unit
            # so we want to _internal_lshift dummy.unit by little_shift
            dummy._internal_lshift(little_shift)
            # and then write
            # self = p^(ppow) * (x^e/p)^(ppow) * dummy.unit
            # so we need to multiply dummy.unit by (p/x^e)^(-ppow) in the Eisenstein case
            # which we can do by _pshift_self
            dummy._pshift_self(-ppow)
            ans.x = dummy.unit
        ans.c = ctx
        return ans, ans_k

    cdef ZZ_p_c _const_term(self):
        """
        Returns the constant term of ``self.unit``.

        Note: this may be divisible by `p` if ``self`` is not normalized.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(566)
            sage: a._const_term_test() #indirect doctest
            566
        """
        return ZZ_pX_ConstTerm((<pAdicZZpXCRElement>self).unit)

    def is_equal_to(self, right, absprec = None):
        """
        Returns whether ``self`` is equal to ``right`` modulo ``self.uniformizer()^absprec``.

        If ``absprec`` is ``None``, returns if ``self`` is equal to ``right`` modulo the lower of their two precisions.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(47); b = W(47 + 25)
            sage: a.is_equal_to(b)
            False
            sage: a.is_equal_to(b, 7)
            True
        """
        # Should be sped up later
        return (self - right).is_zero(absprec)

#    def lift(self):
#        """
#        Returns an element of a number field defined by the same polynomial as self's parent that is congruent to self modulo an appropriate ideal.

#        Not currently implemented.
#        """
#        raise NotImplementedError

    cpdef pAdicZZpXCRElement lift_to_precision(self, absprec=None):
        """
        Returns a ``pAdicZZpXCRElement`` congruent to ``self`` but with
        absolute precision at least ``absprec``.

        INPUT:

        - ``absprec`` -- (default ``None``) the absolute precision of
          the result.  If ``None``, lifts to the maximum precision
          allowed.

        .. NOTE::

            If setting ``absprec`` that high would violate the
            precision cap, raises a precision error.  If self is an
            inexact zero and ``absprec`` is greater than the maximum
            allowed valuation, raises an error.

            Note that the new digits will not necessarily be zero.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(345, 17); a
            4*w^5 + 3*w^7 + w^9 + 3*w^10 + 2*w^11 + 4*w^12 + w^13 + 2*w^14 + 2*w^15 + O(w^17)
            sage: b = a.lift_to_precision(19); b
            4*w^5 + 3*w^7 + w^9 + 3*w^10 + 2*w^11 + 4*w^12 + w^13 + 2*w^14 + 2*w^15 + w^17 + 2*w^18 + O(w^19)
            sage: c = a.lift_to_precision(24); c
            4*w^5 + 3*w^7 + w^9 + 3*w^10 + 2*w^11 + 4*w^12 + w^13 + 2*w^14 + 2*w^15 + w^17 + 2*w^18 + 4*w^19 + 4*w^20 + 2*w^21 + 4*w^23 + O(w^24)
            sage: a._ntl_rep()
            [19 35 118 60 121]
            sage: b._ntl_rep()
            [19 35 118 60 121]
            sage: c._ntl_rep()
            [19 35 118 60 121]
            sage: a.lift_to_precision().precision_relative() == W.precision_cap()
            True
        """
        cdef pAdicZZpXCRElement ans
        cdef long aprec, rprec
        self._normalize()
        if self._is_exact_zero():
            return self
        if absprec is not None and not PY_TYPE_CHECK(absprec, Integer):
            absprec = Integer(absprec)
        if absprec is None:
            if self.relprec == 0:
                # return an exact zero
                ans = self._new_c(0)
                ans._set_exact_zero()
                return ans
            aprec = self.prime_pow.ram_prec_cap + self.ordp
        elif mpz_fits_slong_p((<Integer>absprec).value) == 0:
            if mpz_sgn((<Integer>absprec).value) < 0 or self.relprec == self.prime_pow.ram_prec_cap:
                return self
            else:
                if self.relprec == 0:
                    raise ValueError("absprec larger than maximum allowable valuation")
                else:
                    raise PrecisionError("Precision higher than allowed by the precision cap.")
        else:
            aprec = mpz_get_si((<Integer>absprec).value)
        if aprec <= self.ordp + self.relprec:
            return self
        if self.relprec == 0:
            if self.ordp >= aprec:
                return self
            elif aprec >= maxordp:
                raise ValueError("absprec larger than maximum allowable valuation")
            else:
                ans = self._new_c(0)
                ans._set_inexact_zero(aprec)
                return ans
        # Now we're done handling all the special cases.
        rprec = aprec - self.ordp
        if rprec > self.prime_pow.ram_prec_cap:
            raise PrecisionError("Precision higher than allowed by the precision cap.")
        ans = self._new_c(rprec)
        ans.ordp = self.ordp
        ZZ_pX_conv_modulus(ans.unit, self.unit, self.prime_pow.get_context_capdiv(rprec).x)
        return ans

    def list(self, lift_mode = 'simple'):
        """
        Returns a list giving a series representation of self.

        - If ``lift_mode == 'simple'`` or ``'smallest'``, the returned
          list will consist of integers (in the Eisenstein case) or a
          list of lists of integers (in the unramified case).  ``self``
          can be reconstructed as a sum of elements of the list times
          powers of the uniformiser (in the Eisenstein case), or as a
          sum of powers of the `p` times polynomials in the generator
          (in the unramified case).

          + If ``lift_mode == 'simple'``, all integers will be in the interval
            `[0,p-1]`.

          + If ``lift_mode == 'smallest'`` they will be in the
            interval `[(1-p)/2, p/2]`.

        - If ``lift_mode == 'teichmuller'``, returns a list of
          ``pAdicZZpXCRElements``, all of which are Teichmuller
          representatives and such that ``self`` is the sum of that list
          times powers of the uniformizer.

        Note that zeros are truncated from the returned list if
        ``self.parent()`` is a field, so you must use the
        ``valuation`` function to fully reconstruct ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: y = W(775, 19); y
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
            sage: (y>>9).list()
            [0, 1, 0, 4, 0, 2, 1, 2, 4, 1]
            sage: (y>>9).list('smallest')
            [0, 1, 0, -1, 0, 2, 1, 2, 0, 1]
            sage: w^10 - w^12 + 2*w^14 + w^15 + 2*w^16 + w^18 + O(w^19)
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
            sage: g = x^3 + 3*x + 3
            sage: A.<a> = R.ext(g)
            sage: y = 75 + 45*a + 1200*a^2; y
            4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
            sage: y.list()
            [[], [0, 4], [3, 1, 3], [0, 0, 4], [0, 0, 1]]
            sage: y.list('smallest')
            [[], [0, -1], [-2, 2, -2], [1], [0, 0, 2]]
            sage: 5*((-2*5 + 25) + (-1 + 2*5)*a + (-2*5 + 2*125)*a^2)
            4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
            sage: W(0).list()
            []
            sage: W(0,4).list()
            [0]
            sage: A(0,4).list()
            [[]]
        """
        cdef pAdicZZpXCRElement zero
        cdef Integer ordp
        if self._is_exact_zero():
            return []
        elif self._is_inexact_zero():
            if lift_mode == 'teichmuller':
                zero = self._new_c(0)
                zero._set_inexact_zero(self.ordp)
                return [zero]
            elif self.prime_pow.e == 1:
                return [[]]
            else:
                return [Integer(0)]
        if lift_mode == 'simple':
            ulist = self.ext_p_list(1)
        elif lift_mode == 'smallest':
            ulist = self.ext_p_list(0)
        elif lift_mode == 'teichmuller':
            ulist = self.teichmuller_list()
        else:
            raise ValueError, "lift mode must be one of 'simple', 'smallest' or 'teichmuller'"
        if self.prime_pow.in_field == 0 and self.ordp > 0:
            ordp = PY_NEW(Integer)
            mpz_set_si(ordp.value, self.ordp)
            if lift_mode == 'teichmuller':
                zero = self._new_c(0)
                return [zero]*ordp + ulist
            elif self.prime_pow.e == 1:
                return [[]] * ordp + ulist
            else:
                return [Integer(0)] * ordp + ulist
        else:
            return ulist

    def matrix_mod_pn(self):
        """
        Returns the matrix of right multiplication by the element on
        the power basis `1, x, x^2, \ldots, x^{d-1}` for this
        extension field.  Thus the *rows* of this matrix give the
        images of each of the `x^i`.  The entries of the matrices are
        IntegerMod elements, defined modulo `p^{N / e}` where `N` is
        the absolute precision of this element (unless this element is
        zero to arbitrary precision; in that case the entries are
        integer zeros.)

        Raises an error if this element has negative valuation.

        EXAMPLES::

            sage: R = ZpCR(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = (3+w)^7
            sage: a.matrix_mod_pn()
            [2757  333 1068  725 2510]
            [  50 1507  483  318  725]
            [ 500   50 3007 2358  318]
            [1590 1375 1695 1032 2358]
            [2415  590 2370 2970 1032]

        TESTS:

        Check that :trac:`13617` has been fixed::

            sage: W.zero().matrix_mod_pn()
            [0 0 0 0 0]
            [0 0 0 0 0]
            [0 0 0 0 0]
            [0 0 0 0 0]
            [0 0 0 0 0]

        """
        if self.valuation_c() < 0:
            raise ValueError, "self must be integral"
        n = self.prime_pow.deg
        from sage.matrix.all import matrix
        if self._is_exact_zero():
            from sage.rings.integer_ring import IntegerRing
            return matrix(IntegerRing(), n, n)
        R = IntegerModRing(self.prime_pow.pow_Integer(self.prime_pow.capdiv(self.ordp + self.relprec)))
        L = []
        cdef ntl_ZZ_pX cur = <ntl_ZZ_pX>self._ntl_rep_abs()[0]
        cur.c.restore_c()
        cdef ZZ_pX_Modulus_c* m = self.prime_pow.get_modulus_capdiv(self.ordp + self.relprec)
        cdef ZZ_pX_c x
        ZZ_pX_SetX(x)
        cdef Py_ssize_t i, j
        zero = int(0)
        for i from 0 <= i < n:
            curlist = cur.list()
            L.extend(curlist + [zero]*(n - len(curlist)))
            ZZ_pX_MulMod_pre(cur.x, cur.x, x, m[0])
        return matrix(R, n, n,  L)

#     def matrix(self, base = None):
#         """
#         If base is None, return the matrix of right multiplication by
#         the element on the power basis `1, x, x^2, \ldots, x^{d-1}`
#         for this extension field.  Thus the \emph{rows} of this matrix
#         give the images of each of the `x^i`.

#         If base is not None, then base must be either a field that
#         embeds in the parent of self or a morphism to the parent of
#         self, in which case this function returns the matrix of
#         multiplication by self on the power basis, where we view the
#         parent field as a field over base.

#         INPUT:
#             base -- field or morphism
#         """
#         raise NotImplementedError

#     def multiplicative_order(self, prec=None):
#         """
#         Returns the multiplicative order of self, ie the smallest
#         positive n so that there is an exact p-adic element congruent
#         to self modulo self's precision that is an nth root of unity.

#         Note: unlike the case for Qp and Zp, it is possible to have
#         non-teichmuller elements with finite orders.  This can happen
#         only if (p-1) divides the ramification index (see the
#         documentation on __pow__).

#         INPUT:

#             - self -- a p-adic element
#             - prec -- an integer

#         OUTPUT:

#             - integer -- the multiplicative order of self
#         """
#         raise NotImplementedError

    def teichmuller_list(self):
        r"""
        Returns a list [`a_0`, `a_1`,..., `a_n`] such that

        - `a_i^q = a_i`
        - ``self.unit_part()`` = `\sum_{i = 0}^n a_i \pi^i`, where `\pi` is a
          uniformizer of ``self.parent()``
        - if `a_i \ne 0`, the absolute precision of `a_i` is
          ``self.precision_relative() - i``

        EXAMPLES::

            sage: R.<a> = ZqCR(5^4,4)
            sage: L = a.teichmuller_list(); L
            [a + (2*a^3 + 2*a^2 + 3*a + 4)*5 + (4*a^3 + 3*a^2 + 3*a + 2)*5^2 + (4*a^2 + 2*a + 2)*5^3 + O(5^4), (3*a^3 + 3*a^2 + 2*a + 1) + (a^3 + 4*a^2 + 1)*5 + (a^2 + 4*a + 4)*5^2 + O(5^3), (4*a^3 + 2*a^2 + a + 1) + (2*a^3 + 2*a^2 + 2*a + 4)*5 + O(5^2), (a^3 + a^2 + a + 4) + O(5)]
            sage: sum([5^i*L[i] for i in range(4)])
            a + O(5^4)
            sage: all([L[i]^625 == L[i] for i in range(4)])
            True

            sage: S.<x> = ZZ[]
            sage: f = x^3 - 98*x + 7
            sage: W.<w> = ZpCR(7,3).ext(f)
            sage: b = (1+w)^5; L = b.teichmuller_list(); L
            [1 + O(w^9), 5 + 5*w^3 + w^6 + 4*w^7 + O(w^8), 3 + 3*w^3 + O(w^7), 3 + 3*w^3 + O(w^6), O(w^5), 4 + 5*w^3 + O(w^4), 3 + O(w^3), 6 + O(w^2), 6 + O(w)]
            sage: sum([w^i*L[i] for i in range(9)]) == b
            True
            sage: all([L[i]^(7^3) == L[i] for i in range(9)])
            True

            sage: L = W(3).teichmuller_list(); L
            [3 + 3*w^3 + w^7 + O(w^9), O(w^8), O(w^7), 4 + 5*w^3 + O(w^6), O(w^5), O(w^4), 3 + O(w^3), 6 + O(w^2)]
            sage: sum([w^i*L[i] for i in range(len(L))])
            3 + O(w^9)
        """
        L = []
        cdef long rp = self.relprec
        if rp == 0:
            return L
        cdef pAdicZZpXCRElement u = self.unit_part()
        cdef pAdicZZpXCRElement v
        while u.relprec > 0:
            v = self._new_c(rp)
            self.prime_pow.teichmuller_set_c(&v.unit, &u.unit, rp)
            v.ordp = 0
            L.append(v)
            if rp == 1: break
            ZZ_pX_sub(u.unit, u.unit, v.unit)
            u.relprec = -u.relprec
            u._normalize()
            if u.relprec == 0: break
            rp -= 1
            u.ordp -= 1
            while u.ordp > 0:
                v = self._new_c(0)
                v._set_inexact_zero(rp)
                L.append(v)
                rp -= 1
                u.ordp -= 1
        return L

    def _teichmuller_set_unsafe(self):
        """
        Sets this element to the Teichmuller representative with the
        same residue.

        .. WARNING::

            This function modifies the element, which is not safe.
            Elements are supposed to be immutable.

        EXAMPLES::

            sage: R = Zp(7,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 77*x^3 - 98*x^2 - 7
            sage: W.<w> = R.ext(f)
            sage: y = W.teichmuller(3, 15); y #indirect doctest
            3 + 4*w^5 + 2*w^8 + 6*w^10 + w^11 + 6*w^12 + 5*w^13 + 4*w^14 + O(w^15)

            sage: y^7 == y
            True
            sage: g = x^3 + 3*x^2 + 4
            sage: A.<a> = R.ext(g)
            sage: b = A.teichmuller(1 + 2*a - a^2); b
            (6*a^2 + 2*a + 1) + (5*a + 3)*7 + (5*a + 5)*7^2 + (4*a^2 + 4*a + 2)*7^3 + (2*a + 1)*7^4 + O(7^5)
            sage: b^343 == b
            True

        TESTS:

        We check that #8239 is resolved::

            sage: K.<a> = Qq(25)
            sage: K.teichmuller(K(2/5))
            Traceback (most recent call last):
            ...
            ValueError: cannot set negative valuation element to Teichmuller representative.
        """
        self._normalize()
        if self.ordp > 0:
            self._set_exact_zero()
        elif self.ordp < 0:
            raise ValueError, "cannot set negative valuation element to Teichmuller representative."
        elif self.relprec == 0:
            raise ValueError, "not enough precision known"
        else:
            self.prime_pow.teichmuller_set_c(&self.unit, &self.unit, self.relprec)

#    def padded_list(self, n, lift_mode = 'simple'):
#        """
#        Returns a list of coefficients of pi starting with `pi^0` up to
#        `pi^n` exclusive (padded with zeros if needed)

#        """
#        raise NotImplementedError

    def precision_absolute(self):
        """
        Returns the absolute precision of ``self``, ie the power of the
        uniformizer modulo which this element is defined.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(75, 19); a
            3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
            sage: a.valuation()
            10
            sage: a.precision_absolute()
            19
            sage: a.precision_relative()
            9
            sage: a.unit_part()
            3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
            sage: (a.unit_part() - 3).precision_absolute()
            9
        """
        cdef Integer ans
        if self.ordp == maxordp:
            return infinity
        else:
            ans = PY_NEW(Integer)
            if self.relprec > 0:
                mpz_set_si(ans.value, self.relprec + self.ordp)
            else:
                mpz_set_si(ans.value, -self.relprec + self.ordp)
            return ans

    def precision_relative(self):
        """
        Returns the relative precision of ``self``, ie the power of the
        uniformizer modulo which the unit part of ``self`` is defined.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(75, 19); a
            3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
            sage: a.valuation()
            10
            sage: a.precision_absolute()
            19
            sage: a.precision_relative()
            9
            sage: a.unit_part()
            3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
        """
        self._normalize()
        cdef Integer ans = PY_NEW(Integer)
        mpz_set_ui(ans.value, self.relprec)
        return ans

#    def residue(self, n = 1):
#        """
#        Reduces this element modulo pi^n.
#        """
#        raise NotImplementedError

    cdef long valuation_c(self):
        """
        Returns the valuation of ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(75, 19); a
            3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
            sage: a.valuation() # indirect doctest
            10
            sage: a.precision_absolute()
            19
            sage: a.precision_relative()
            9
            sage: a.unit_part()
            3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)
        """
        self._normalize()
        return self.ordp

    cpdef pAdicZZpXCRElement unit_part(self):
        """
        Returns the unit part of ``self``, ie ``self / uniformizer^(self.valuation())``

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: a = W(75, 19); a
            3*w^10 + 2*w^12 + w^14 + w^16 + w^17 + 3*w^18 + O(w^19)
            sage: a.valuation()
            10
            sage: a.precision_absolute()
            19
            sage: a.precision_relative()
            9
            sage: a.unit_part()
            3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + O(w^9)

        TESTS:

        We check that :trac:`13616` is resolved::

            sage: z = (1+w)^5
            sage: y = z - 1
            sage: t=y-y
            sage: t.unit_part()
            O(w^0)
        """
        self._normalize()
        cdef pAdicZZpXCRElement ans = self._new_c(self.relprec)
        ans.ordp = 0
        if self.relprec != 0:
            ans.unit = self.unit
        return ans

    cdef ext_p_list(self, bint pos):
        """
        Returns a list of integers (in the Eisenstein case) or a list
        of lists of integers (in the unramified case).  ``self`` can be
        reconstructed as a sum of elements of the list times powers of
        the uniformiser (in the Eisenstein case), or as a sum of
        powers of `p` times polynomials in the generator (in the
        unramified case).

        If ``pos`` is ``True``, all integers will be in the interval `[0,p-1]`,
        otherwise they will be in the interval `[(1-p)/2, p/2]`.

        Note that zeros are truncated from the returned list, so you
        must use the ``valuation()`` function to completely recover ``self``.

        EXAMPLES::

            sage: R = Zp(5,5)
            sage: S.<x> = R[]
            sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
            sage: W.<w> = R.ext(f)
            sage: y = W(775, 19); y
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
            sage: y._ext_p_list(True)
            [1, 0, 4, 0, 2, 1, 2, 4, 1]
            sage: y._ext_p_list(False)
            [1, 0, -1, 0, 2, 1, 2, 0, 1]
            sage: w^10 - w^12 + 2*w^14 + w^15 + 2*w^16 + w^18 + O(w^19)
            w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
            sage: g = x^3 + 3*x + 3
            sage: A.<a> = R.ext(g)
            sage: y = 75 + 45*a + 1200*a^2; y
            4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
            sage: y._ext_p_list(True)
            [[0, 4], [3, 1, 3], [0, 0, 4], [0, 0, 1]]
            sage: y._ext_p_list(False)
            [[0, -1], [-2, 2, -2], [1], [0, 0, 2]]
            sage: 5*((-2*5 + 25) + (-1 + 2*5)*a + (-2*5 + 2*125)*a^2)
            4*a*5 + (3*a^2 + a + 3)*5^2 + 4*a^2*5^3 + a^2*5^4 + O(5^6)
        """
        self._normalize()
        return self.ext_p_list_precs(pos, self.relprec)

def make_ZZpXCRElement(parent, unit, ordp, relprec, version):
    """
    Unpickling.

    EXAMPLES::

        sage: R = Zp(5,5)
        sage: S.<x> = R[]
        sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5
        sage: W.<w> = R.ext(f)
        sage: y = W(775, 19); y
        w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)
        sage: loads(dumps(y)) #indirect doctest
        w^10 + 4*w^12 + 2*w^14 + w^15 + 2*w^16 + 4*w^17 + w^18 + O(w^19)

        sage: from sage.rings.padics.padic_ZZ_pX_CR_element import make_ZZpXCRElement
        sage: make_ZZpXCRElement(W, y._ntl_rep(), 3, 9, 0)
        w^3 + 4*w^5 + 2*w^7 + w^8 + 2*w^9 + 4*w^10 + w^11 + O(w^12)
    """
    cdef pAdicZZpXCRElement ans
    cdef ZZ_pX_c poly
    if version == 0:
        ans = pAdicZZpXCRElement(parent, [], empty = True)
        if relprec == 0:
            ans._set_inexact_zero(mpz_get_si((<Integer>ordp).value))
        else:
            ans.prime_pow.restore_context_capdiv(mpz_get_si((<Integer>relprec).value))
            poly = (<ntl_ZZ_pX>unit).x
            ans._set(&poly, mpz_get_si((<Integer>ordp).value), mpz_get_si((<Integer>relprec).value))
        return ans
    else:
        raise ValueError, "unknown unpickling version"
