\(p\)-Adic ZZ_pX CR Element

\(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
sage.rings.padics.padic_ZZ_pX_CR_element.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)
class sage.rings.padics.padic_ZZ_pX_CR_element.pAdicZZpXCRElement

Bases: sage.rings.padics.padic_ZZ_pX_element.pAdicZZpXElement

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 ticket #3865 is fixed:

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

Check that trac ticket #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)
is_equal_to(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
is_zero(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
lift_to_precision(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
list(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()
[[]]
matrix_mod_pn()

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 ticket #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]
precision_absolute()

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
precision_relative()

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)
teichmuller_list()

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)
unit_part()

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 ticket #13616 is resolved:

sage: z = (1+w)^5
sage: y = z - 1
sage: t=y-y
sage: t.unit_part()
O(w^0)

Previous topic

\(p\)-Adic ZZ_pX Element

Next topic

\(p\)-Adic ZZ_pX CA Element

This Page