Elements of p-Adic Rings and Fields
AUTHOR:
Divides self by right and throws away the nonintegral part if self.parent() is not a field.
There are a number of reasonable definitions for floor division. Any definition should satisfy the following identity:
If a and b lie in a field, then setting a % b = 0 and a // b = a / b provides a canonical way of satisfying this equation.
However, for elements of integer rings, there are many choices of definitions for a // b and a % b that satisfy this equation. Since p-adic rings in Sage come equipped with a uniformizer pi, we can use the choice of uniformizer in our definitions. Here are some other criteria we might ask for:
(2) If b = pi^k, the series expansion (in terms of pi) of a // b is just the series expansion of a, shifted over by k terms.
(2’) The series expansion of a % pi^k has no terms above pi^(k-1).
The conditions (2) and (2’) are equivalent. But when we generalize these conditions to arbitrary b they diverge.
(3) For general b, the series expansion of a // b is just the series expansion of a / b, truncating terms with negative exponents of pi.
(4) For general b, the series expansion of a % b has no terms above b.valuation() - 1.
In order to satisfy (3), one defines
a // b = (a / b.unit_part()) >> b.valuation() a % b = a - (a // b) * b
In order to satisfy (4), one defines
a % b = a.lift() % pi.lift()^b.valuation() a // b = ((a - a % b) >> b.valuation()) / b.unit_part()
In Sage we choose option (3), mainly because it is more easily defined in terms of shifting and thus generalizes more easily to extension rings.
EXAMPLES:
sage: R = ZpCA(5); a = R(129378); b = R(2398125)
sage: a // b #indirect doctest
3 + 3*5 + 4*5^2 + 2*5^4 + 2*5^6 + 4*5^7 + 5^9 + 5^10 + 5^11 + O(5^12)
sage: a / b
4*5^-4 + 3*5^-3 + 2*5^-2 + 5^-1 + 3 + 3*5 + 4*5^2 + 2*5^4 + 2*5^6 + 4*5^7 + 5^9 + 5^10 + 5^11 + O(5^12)
sage: a % b
3 + 5^4 + 3*5^5 + 2*5^6 + 4*5^7 + 5^8 + O(5^16)
sage: (a // b) * b + a % b
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^16)
The alternative definition:
sage: a
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
sage: c = ((a - 3)>>4)/b.unit_part(); c
1 + 2*5 + 2*5^3 + 4*5^4 + 5^6 + 5^7 + 5^8 + 4*5^9 + 2*5^10 + 4*5^11 + 4*5^12 + 2*5^13 + 3*5^14 + O(5^16)
sage: c*b + 3
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
Returns the coefficient of $p^n$ in the series expansion of self, as an integer in the range $0$ to $p-1$.
EXAMPLE:
sage: R = Zp(7,4,'capped-rel','series'); a = R(1/3); a
5 + 4*7 + 4*7^2 + 4*7^3 + O(7^4)
sage: a[0] #indirect doctest
5
sage: a[1]
4
Returns the multiplicative inverse of self.
EXAMPLE:
sage: R = Zp(7,4,'capped-rel','series'); a = R(3); a
3 + O(7^4)
sage: ~a #indirect doctest
5 + 4*7 + 4*7^2 + 4*7^3 + O(7^4)
NOTES:
The element returned is an element of the fraction field.
If self is in a field, returns 0. If in a ring, returns a p-adic integer such that
holds.
WARNING: The series expansion of a % b continues above the valuation of b.
The definitions of a // b and a % b are intertwined by equation (1). If a and b lie in a field, then setting a % b = 0 and a // b = a / b provides a canonical way of satisfying this equation.
However, for elements of integer rings, there are many choices of definitions for a // b and a % b that satisfy this equation. Since p-adic rings in Sage come equipped with a uniformizer pi, we can use the choice of uniformizer in our definitions. Here are some other criteria we might ask for:
(2) If b = pi^k, the series expansion (in terms of pi) of a // b is just the series expansion of a, shifted over by k terms.
(2’) The series expansion of a % pi^k has no terms above pi^(k-1).
The conditions (2) and (2’) are equivalent. But when we generalize these conditions to arbitrary b they diverge.
(3) For general b, the series expansion of a // b is just the series expansion of a / b, truncating terms with negative exponents of pi.
(4) For general b, the series expansion of a % b has no terms above b.valuation() - 1.
In order to satisfy (3), one defines
a // b = (a / b.unit_part()) >> b.valuation() a % b = a - (a // b) * b
In order to satisfy (4), one defines
a % b = a.lift() % pi.lift()^b.valuation() a // b = ((a - a % b) >> b.valuation()) / b.unit_part()
In Sage we choose option (3), mainly because it is more easily defined in terms of shifting and thus generalizes more easily to extension rings.
EXAMPLES:
sage: R = ZpCA(5); a = R(129378); b = R(2398125)
sage: a // b
3 + 3*5 + 4*5^2 + 2*5^4 + 2*5^6 + 4*5^7 + 5^9 + 5^10 + 5^11 + O(5^12)
sage: a / b
4*5^-4 + 3*5^-3 + 2*5^-2 + 5^-1 + 3 + 3*5 + 4*5^2 + 2*5^4 + 2*5^6 + 4*5^7 + 5^9 + 5^10 + 5^11 + O(5^12)
sage: a % b #indirect doctest
3 + 5^4 + 3*5^5 + 2*5^6 + 4*5^7 + 5^8 + O(5^16)
The alternative definition:
sage: a
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
sage: c = ((a - 3)>>4)/b.unit_part(); c
1 + 2*5 + 2*5^3 + 4*5^4 + 5^6 + 5^7 + 5^8 + 4*5^9 + 2*5^10 + 4*5^11 + 4*5^12 + 2*5^13 + 3*5^14 + O(5^16)
sage: c*b + 3
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
Returns True if self is exactly zero. Since non-capped-relative elements cannot be exact, this function always returns False.
EXAMPLES:
sage: ZpCA(17)(0)._is_exact_zero()
False
Returns True if self is indistinguishable from zero, but not exactly zero.
EXAMPLES:
sage: Zp(5)(0,5)._is_inexact_zero()
True
Returns True is self is indistinguishable from zero.
EXAMPLES:
sage: ZpCA(17)(0,15)._is_zero_rep()
True
Returns a string representation of self.
INPUTS:
- mode -- allows one to override the default print mode of
the parent (default None).
- do_latex -- whether to return a latex representation or
a normal one.
EXAMPLES:
sage: Zp(5,5)(1/3) # indirect doctest
2 + 3*5 + 5^2 + 3*5^3 + 5^4 + O(5^5)
Returns the p-adic absolute value of self.
This is normalized so that the absolute value of p is 1/p.
INPUT:
- prec -- Integer. The precision of the real field in
which the answer is returned. If None, returns a
rational for absolutely unramified fields, or a real
with 53 bits of precision if ramified.
EXAMPLES:
sage: a = Qp(5)(15); a.abs()
1/5
sage: a.abs(53)
0.200000000000000
Returns the additive order of self, where self is considered to be zero if it is zero modulo $p^{mbox{prec}}$.
INPUT:
self -- a p-adic element
prec -- an integer
OUTPUT:
integer -- the additive order of self
EXAMPLES:
sage: R = Zp(7, 4, 'capped-rel', 'series'); a = R(7^3); a.additive_order(3)
1
sage: a.additive_order(4)
+Infinity
sage: R = Zp(7, 4, 'fixed-mod', 'series'); a = R(7^5); a.additive_order(6)
1
Returns a polynomial of degree at most $n$ which is approximately satisfied by this number. Note that the returned polynomial need not be irreducible, and indeed usually won’t be if this number is a good approximation to an algebraic number of degree less than $n$.
ALGORITHM:
Uses the PARI C-library algdep command.
INPUT:
- self -- a p-adic element
- n -- an integer
OUTPUT:
polynomial -- degree n polynomial approximately satisfied by self
EXAMPLES:
sage: K = Qp(3,20,'capped-rel','series'); R = Zp(3,20,'capped-rel','series')
sage: a = K(7/19); a
1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12 + 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20)
sage: a.algdep(1)
19*x - 7
sage: K2 = Qp(7,20,'capped-rel')
sage: b = K2.zeta(); b.algdep(2)
x^2 - x + 1
sage: K2 = Qp(11,20,'capped-rel')
sage: b = K2.zeta(); b.algdep(4)
x^4 - x^3 + x^2 - x + 1
sage: a = R(7/19); a
1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12 + 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20)
sage: a.algdep(1)
19*x - 7
sage: R2 = Zp(7,20,'capped-rel')
sage: b = R2.zeta(); b.algdep(2)
x^2 - x + 1
sage: R2 = Zp(11,20,'capped-rel')
sage: b = R2.zeta(); b.algdep(4)
x^4 - x^3 + x^2 - x + 1
Returns a polynomial of degree at most $n$ which is approximately satisfied by this number. Note that the returned polynomial need not be irreducible, and indeed usually won’t be if this number is a good approximation to an algebraic number of degree less than $n$.
ALGORITHM:
Uses the PARI C-library algdep command.
INPUT:
- self -- a p-adic element
- n -- an integer
OUTPUT:
polynomial -- degree n polynomial approximately satisfied by self
EXAMPLES:
sage: K = Qp(3,20,'capped-rel','series'); R = Zp(3,20,'capped-rel','series')
sage: a = K(7/19); a
1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12 + 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20)
sage: a.algebraic_dependency(1)
19*x - 7
sage: K2 = Qp(7,20,'capped-rel')
sage: b = K2.zeta(); b.algebraic_dependency(2)
x^2 - x + 1
sage: K2 = Qp(11,20,'capped-rel')
sage: b = K2.zeta(); b.algebraic_dependency(4)
x^4 - x^3 + x^2 - x + 1
sage: a = R(7/19); a
1 + 2*3 + 3^2 + 3^3 + 2*3^4 + 2*3^5 + 3^8 + 2*3^9 + 3^11 + 3^12 + 2*3^15 + 2*3^16 + 3^17 + 2*3^19 + O(3^20)
sage: a.algebraic_dependency(1)
19*x - 7
sage: R2 = Zp(7,20,'capped-rel')
sage: b = R2.zeta(); b.algebraic_dependency(2)
x^2 - x + 1
sage: R2 = Zp(11,20,'capped-rel')
sage: b = R2.zeta(); b.algebraic_dependency(4)
x^4 - x^3 + x^2 - x + 1
Returns whether self is a square
INPUT:
self -- a p-adic element
OUTPUT:
boolean -- whether self is a square
EXAMPLES:
sage: R = Zp(3,20,'capped-rel')
sage: R(0).is_square()
True
sage: R(1).is_square()
True
sage: R(2).is_square()
False
TESTS:
sage: R(3).is_square()
False
sage: R(4).is_square()
True
sage: R(6).is_square()
False
sage: R(9).is_square()
True
sage: R2 = Zp(2,20,'capped-rel')
sage: R2(0).is_square()
True
sage: R2(1).is_square()
True
sage: R2(2).is_square()
False
sage: R2(3).is_square()
False
sage: R2(4).is_square()
True
sage: R2(5).is_square()
False
sage: R2(6).is_square()
False
sage: R2(7).is_square()
False
sage: R2(8).is_square()
False
sage: R2(9).is_square()
True
sage: K = Qp(3,20,'capped-rel')
sage: K(0).is_square()
True
sage: K(1).is_square()
True
sage: K(2).is_square()
False
sage: K(3).is_square()
False
sage: K(4).is_square()
True
sage: K(6).is_square()
False
sage: K(9).is_square()
True
sage: K(1/3).is_square()
False
sage: K(1/9).is_square()
True
sage: K2 = Qp(2,20,'capped-rel')
sage: K2(0).is_square()
True
sage: K2(1).is_square()
True
sage: K2(2).is_square()
False
sage: K2(3).is_square()
False
sage: K2(4).is_square()
True
sage: K2(5).is_square()
False
sage: K2(6).is_square()
False
sage: K2(7).is_square()
False
sage: K2(8).is_square()
False
sage: K2(9).is_square()
True
sage: K2(1/2).is_square()
False
sage: K2(1/4).is_square()
True
Returns the multiplicative order of self, where self is considered to be one if it is one modulo $p^{mbox{prec}}$.
INPUT:
self -- a p-adic element
prec -- an integer
OUTPUT:
integer -- the multiplicative order of self
EXAMPLES:
sage: K = Qp(5,20,'capped-rel')
sage: K(-1).multiplicative_order(20)
2
sage: K(1).multiplicative_order(20)
1
sage: K(2).multiplicative_order(20)
+Infinity
sage: K(3).multiplicative_order(20)
+Infinity
sage: K(4).multiplicative_order(20)
+Infinity
sage: K(5).multiplicative_order(20)
+Infinity
sage: K(25).multiplicative_order(20)
+Infinity
sage: K(1/5).multiplicative_order(20)
+Infinity
sage: K(1/25).multiplicative_order(20)
+Infinity
sage: K.zeta().multiplicative_order(20)
4
sage: R = Zp(5,20,'capped-rel')
sage: R(-1).multiplicative_order(20)
2
sage: R(1).multiplicative_order(20)
1
sage: R(2).multiplicative_order(20)
+Infinity
sage: R(3).multiplicative_order(20)
+Infinity
sage: R(4).multiplicative_order(20)
+Infinity
sage: R(5).multiplicative_order(20)
+Infinity
sage: R(25).multiplicative_order(20)
+Infinity
sage: R.zeta().multiplicative_order(20)
4
Returns the valuation of self, normalized so that the valuation of p is 1
INPUT:
self -- a p-adic element
OUTPUT:
integer -- the valuation of self, normalized so that the valuation of p is 1
EXAMPLES:
sage: R = Zp(5,20,'capped-rel')
sage: R(0).ordp()
+Infinity
sage: R(1).ordp()
0
sage: R(2).ordp()
0
sage: R(5).ordp()
1
sage: R(10).ordp()
1
sage: R(25).ordp()
2
sage: R(50).ordp()
2
sage: R(1/2).ordp()
0
Returns a rational approximation to this p-adic number
INPUT:
self -- a p-adic element
OUTPUT:
rational -- an approximation to self
EXAMPLES:
sage: R = Zp(5,20,'capped-rel')
sage: for i in range(11):
... for j in range(1,10):
... if j == 5:
... continue
... assert i/j == R(i/j).rational_reconstruction()
Returns the square root of this p-adic number
INPUT:
- self -- a p-adic element
- extend -- bool (default: True); if True, return a square root
in an extension if necessary; if False and no root exists
in the given ring or field, raise a ValueError
- all -- bool (default: False); if True, return a list of all
square roots
OUTPUT:
p-adic element -- the square root of this p-adic number
If all = False, the square root chosen is the one whose
reduction mod p is in the range [0, p/2).
EXAMPLES:
sage: R = Zp(3,20,'capped-rel', 'val-unit')
sage: R(0).square_root()
0
sage: R(1).square_root()
1 + O(3^20)
sage: R(2).square_root(extend = False)
...
ValueError: element is not a square
sage: R(4).square_root() == R(-2)
True
sage: R(9).square_root()
3 * 1 + O(3^21)
When p = 2, the precision of the square root is one less
than the input:
sage: R2 = Zp(2,20,'capped-rel')
sage: R2(0).square_root()
0
sage: R2(1).square_root()
1 + O(2^19)
sage: R2(4).square_root()
2 + O(2^20)
sage: R2(9).square_root() == R2(3, 19) or R2(9).square_root() == R2(-3, 19)
True
sage: R2(17).square_root()
1 + 2^3 + 2^5 + 2^6 + 2^7 + 2^9 + 2^10 + 2^13 + 2^16 + 2^17 + O(2^19)
sage: R3 = Zp(5,20,'capped-rel')
sage: R3(0).square_root()
0
sage: R3(1).square_root()
1 + O(5^20)
sage: R3(-1).square_root() == R3.teichmuller(2) or R3(-1).square_root() == R3.teichmuller(3)
True
TESTS:
sage: R = Qp(3,20,'capped-rel')
sage: R(0).square_root()
0
sage: R(1).square_root()
1 + O(3^20)
sage: R(4).square_root() == R(-2)
True
sage: R(9).square_root()
3 + O(3^21)
sage: R(1/9).square_root()
3^-1 + O(3^19)
sage: R2 = Qp(2,20,'capped-rel')
sage: R2(0).square_root()
0
sage: R2(1).square_root()
1 + O(2^19)
sage: R2(4).square_root()
2 + O(2^20)
sage: R2(9).square_root() == R2(3,19) or R2(9).square_root() == R2(-3,19)
True
sage: R2(17).square_root()
1 + 2^3 + 2^5 + 2^6 + 2^7 + 2^9 + 2^10 + 2^13 + 2^16 + 2^17 + O(2^19)
sage: R3 = Qp(5,20,'capped-rel')
sage: R3(0).square_root()
0
sage: R3(1).square_root()
1 + O(5^20)
sage: R3(-1).square_root() == R3.teichmuller(2) or R3(-1).square_root() == R3.teichmuller(3)
True
Returns a string representation of self.
EXAMPLES:
sage: Zp(5,5,print_mode='bars')(1/3).str()[3:]
'1|3|1|3|2'
Returns (self.valuation(), self.unit_part()).
EXAMPLES:
sage: Zp(5,5)(5).val_unit()
(1, 1 + O(5^5))
Returns the valuation of self.
INPUT:
- self -- a p-adic element
OUTPUT:
- integer -- the valuation of self
EXAMPLES:
sage: R = Zp(17, 4,'capped-rel')
sage: a = R(2*17^2)
sage: a.valuation()
2
sage: R = Zp(5, 4,'capped-rel')
sage: R(0).valuation()
+Infinity
TESTS:
sage: R(1).valuation()
0
sage: R(2).valuation()
0
sage: R(5).valuation()
1
sage: R(10).valuation()
1
sage: R(25).valuation()
2
sage: R(50).valuation()
2
sage: R = Qp(17, 4)
sage: a = R(2*17^2)
sage: a.valuation()
2
sage: R = Qp(5, 4)
sage: R(0).valuation()
+Infinity
sage: R(1).valuation()
0
sage: R(2).valuation()
0
sage: R(5).valuation()
1
sage: R(10).valuation()
1
sage: R(25).valuation()
2
sage: R(50).valuation()
2
sage: R(1/2).valuation()
0
sage: R(1/5).valuation()
-1
sage: R(1/10).valuation()
-1
sage: R(1/25).valuation()
-2
sage: R(1/50).valuation()
-2