\(p\)-adic Generic Element#
Elements of \(p\)-adic Rings and Fields
AUTHORS:
David Roe
Genya Zaytman: documentation
David Harvey: doctests
Julian Rueth: fixes for exp() and log(), implemented gcd, xgcd
- sage.rings.padics.padic_generic_element.dwork_mahler_coeffs(R, bd=20)[source]#
Compute Dwork’s formula for Mahler coefficients of \(p\)-adic Gamma.
This is called internally when one computes Gamma for a \(p\)-adic integer. Normally there is no need to call it directly.
INPUT:
R
– \(p\)-adic ring in which to computebd
– integer. Number of terms in the expansion to use
OUTPUT:
A list of \(p\)-adic integers.
EXAMPLES:
sage: from sage.rings.padics.padic_generic_element import dwork_mahler_coeffs, evaluate_dwork_mahler sage: R = Zp(3) sage: v = dwork_mahler_coeffs(R) sage: x = R(1/7) sage: evaluate_dwork_mahler(v, x, 3, 20, 1) 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20) sage: x.dwork_expansion(a=1) # Same result 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
>>> from sage.all import * >>> from sage.rings.padics.padic_generic_element import dwork_mahler_coeffs, evaluate_dwork_mahler >>> R = Zp(Integer(3)) >>> v = dwork_mahler_coeffs(R) >>> x = R(Integer(1)/Integer(7)) >>> evaluate_dwork_mahler(v, x, Integer(3), Integer(20), Integer(1)) 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20) >>> x.dwork_expansion(a=Integer(1)) # Same result 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
- sage.rings.padics.padic_generic_element.evaluate_dwork_mahler(v, x, p, bd, a)[source]#
Evaluate Dwork’s Mahler series for \(p\)-adic Gamma.
EXAMPLES:
sage: from sage.rings.padics.padic_generic_element import dwork_mahler_coeffs, evaluate_dwork_mahler sage: R = Zp(3) sage: v = dwork_mahler_coeffs(R) sage: x = R(1/7) sage: evaluate_dwork_mahler(v, x, 3, 20, 1) 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20) sage: x.dwork_expansion(a=1) # Same result 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
>>> from sage.all import * >>> from sage.rings.padics.padic_generic_element import dwork_mahler_coeffs, evaluate_dwork_mahler >>> R = Zp(Integer(3)) >>> v = dwork_mahler_coeffs(R) >>> x = R(Integer(1)/Integer(7)) >>> evaluate_dwork_mahler(v, x, Integer(3), Integer(20), Integer(1)) 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20) >>> x.dwork_expansion(a=Integer(1)) # Same result 2 + 2*3 + 3^2 + 3^3 + 3^4 + 3^5 + 2*3^6 + 2*3^7 + 2*3^8 + 2*3^9 + 2*3^11 + 2*3^12 + 3^13 + 3^14 + 2*3^16 + 3^17 + 3^19 + O(3^20)
- sage.rings.padics.padic_generic_element.gauss_table(p, f, prec, use_longs)[source]#
Compute a table of Gauss sums using the Gross-Koblitz formula.
This is used in the computation of L-functions of hypergeometric motives. The Gross-Koblitz formula is used as in \(sage.rings.padics.misc.gauss_sum\), but further unpacked for efficiency.
INPUT:
p
– primef
,prec
– positive integersuse_longs
– boolean; ifTrue
, computations are done in Clong long
integers rather than Sage \(p\)-adics, and the results are returned as a Python array rather than a list.
OUTPUT:
A list of length \(q-1=p^f-1\). The entries are \(p\)-adic units created with absolute precision
prec
.EXAMPLES:
sage: from sage.rings.padics.padic_generic_element import gauss_table sage: gauss_table(2,2,4,False) [1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3] sage: gauss_table(3,2,4,False)[3] 2 + 3 + 2*3^2
>>> from sage.all import * >>> from sage.rings.padics.padic_generic_element import gauss_table >>> gauss_table(Integer(2),Integer(2),Integer(4),False) [1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3, 1 + 2 + 2^2 + 2^3] >>> gauss_table(Integer(3),Integer(2),Integer(4),False)[Integer(3)] 2 + 3 + 2*3^2
- class sage.rings.padics.padic_generic_element.pAdicGenericElement[source]#
Bases:
LocalGenericElement
- abs(prec=None)[source]#
Return 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. IfNone
, returns a rational for absolutely unramified fields, or a real with 53 bits of precision for ramified fields.
EXAMPLES:
sage: a = Qp(5)(15); a.abs() 1/5 sage: a.abs(53) # needs sage.rings.real_mpfr 0.200000000000000 sage: Qp(7)(0).abs() 0 sage: Qp(7)(0).abs(prec=20) # needs sage.rings.real_mpfr 0.00000
>>> from sage.all import * >>> a = Qp(Integer(5))(Integer(15)); a.abs() 1/5 >>> a.abs(Integer(53)) # needs sage.rings.real_mpfr 0.200000000000000 >>> Qp(Integer(7))(Integer(0)).abs() 0 >>> Qp(Integer(7))(Integer(0)).abs(prec=Integer(20)) # needs sage.rings.real_mpfr 0.00000
An unramified extension:
sage: # needs sage.libs.ntl sage: R = Zp(5,5) sage: P.<x> = PolynomialRing(R) sage: Z25.<u> = R.ext(x^2 - 3) sage: u.abs() 1 sage: (u^24-1).abs() 1/5
>>> from sage.all import * >>> # needs sage.libs.ntl >>> R = Zp(Integer(5),Integer(5)) >>> P = PolynomialRing(R, names=('x',)); (x,) = P._first_ngens(1) >>> Z25 = R.ext(x**Integer(2) - Integer(3), names=('u',)); (u,) = Z25._first_ngens(1) >>> u.abs() 1 >>> (u**Integer(24)-Integer(1)).abs() 1/5
A ramified extension:
sage: # needs sage.libs.ntl sage: W.<w> = R.ext(x^5 + 75*x^3 - 15*x^2 + 125*x - 5) sage: w.abs() 0.724779663677696 sage: W(0).abs() 0.000000000000000
>>> from sage.all import * >>> # needs sage.libs.ntl >>> W = R.ext(x**Integer(5) + Integer(75)*x**Integer(3) - Integer(15)*x**Integer(2) + Integer(125)*x - Integer(5), names=('w',)); (w,) = W._first_ngens(1) >>> w.abs() 0.724779663677696 >>> W(Integer(0)).abs() 0.000000000000000
- additive_order(prec=None)[source]#
Return the additive order of this element truncated at precision
prec
.INPUT:
prec
– an integer orNone
(default:None
)
OUTPUT:
The additive order of this element
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
>>> from sage.all import * >>> R = Zp(Integer(7), Integer(4), 'capped-rel', 'series'); a = R(Integer(7)**Integer(3)); a.additive_order(Integer(3)) 1 >>> a.additive_order(Integer(4)) +Infinity >>> R = Zp(Integer(7), Integer(4), 'fixed-mod', 'series'); a = R(Integer(7)**Integer(5)); a.additive_order(Integer(6)) 1
- algdep(n)[source]#
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 pari:algdep command.
INPUT:
self
– a \(p\)-adic elementn
– 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
>>> from sage.all import * >>> K = Qp(Integer(3),Integer(20),'capped-rel','series'); R = Zp(Integer(3),Integer(20),'capped-rel','series') >>> a = K(Integer(7)/Integer(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) >>> a.algdep(Integer(1)) 19*x - 7 >>> K2 = Qp(Integer(7),Integer(20),'capped-rel') >>> b = K2.zeta(); b.algdep(Integer(2)) x^2 - x + 1 >>> K2 = Qp(Integer(11),Integer(20),'capped-rel') >>> b = K2.zeta(); b.algdep(Integer(4)) x^4 - x^3 + x^2 - x + 1 >>> a = R(Integer(7)/Integer(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) >>> a.algdep(Integer(1)) 19*x - 7 >>> R2 = Zp(Integer(7),Integer(20),'capped-rel') >>> b = R2.zeta(); b.algdep(Integer(2)) x^2 - x + 1 >>> R2 = Zp(Integer(11),Integer(20),'capped-rel') >>> b = R2.zeta(); b.algdep(Integer(4)) x^4 - x^3 + x^2 - x + 1
- algebraic_dependency(n)[source]#
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 pari:algdep command.
INPUT:
self
– a p-adic elementn
– 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
>>> from sage.all import * >>> K = Qp(Integer(3),Integer(20),'capped-rel','series'); R = Zp(Integer(3),Integer(20),'capped-rel','series') >>> a = K(Integer(7)/Integer(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) >>> a.algebraic_dependency(Integer(1)) 19*x - 7 >>> K2 = Qp(Integer(7),Integer(20),'capped-rel') >>> b = K2.zeta(); b.algebraic_dependency(Integer(2)) x^2 - x + 1 >>> K2 = Qp(Integer(11),Integer(20),'capped-rel') >>> b = K2.zeta(); b.algebraic_dependency(Integer(4)) x^4 - x^3 + x^2 - x + 1 >>> a = R(Integer(7)/Integer(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) >>> a.algebraic_dependency(Integer(1)) 19*x - 7 >>> R2 = Zp(Integer(7),Integer(20),'capped-rel') >>> b = R2.zeta(); b.algebraic_dependency(Integer(2)) x^2 - x + 1 >>> R2 = Zp(Integer(11),Integer(20),'capped-rel') >>> b = R2.zeta(); b.algebraic_dependency(Integer(4)) x^4 - x^3 + x^2 - x + 1
- artin_hasse_exp(prec=None, algorithm=None)[source]#
Return the Artin-Hasse exponential of this element.
INPUT:
prec
– an integer orNone
(default:None
) the desired precision on the result; ifNone
, the precision is derived from the precision on the inputalgorithm
–'direct'
,'series'
,'newton'
orNone
(default)The direct algorithm computes the Artin-Hasse exponential of \(x\), namely
AH(x)
as\[AH(x) = \exp(x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \dots\]It runs roughly as fast as the computation of the exponential (since the computation of the argument is not that costly).
The series algorithm computes the series defining the Artin-Hasse exponential and evaluates it.
The
'newton'
algorithm solves the equation\[\log(AH(x)) = x + \frac{x^p}{p} + \frac{x^{p^2}}{p^2} + \dots\]using a Newton scheme. It runs roughly as fast as the computation of the logarithm.
By default, we use the
'direct'
algorithm if a fast algorithm for computing the exponential is available. If not, we use the'newton'
algorithm if a fast algorithm for computing the logarithm is available. Otherwise we switch to the'series'
algorithm.
OUTPUT:
The Artin-Hasse exponential of this element.
See Wikipedia article Artin-Hasse_exponential for more information.
EXAMPLES:
sage: x = Zp(5)(45/7) sage: y = x.artin_hasse_exp(); y 1 + 2*5 + 4*5^2 + 3*5^3 + 5^7 + 2*5^8 + 3*5^10 + 2*5^11 + 2*5^12 + 2*5^13 + 5^14 + 3*5^17 + 2*5^18 + 2*5^19 + O(5^20) sage: y * (-x).artin_hasse_exp() 1 + O(5^20)
>>> from sage.all import * >>> x = Zp(Integer(5))(Integer(45)/Integer(7)) >>> y = x.artin_hasse_exp(); y 1 + 2*5 + 4*5^2 + 3*5^3 + 5^7 + 2*5^8 + 3*5^10 + 2*5^11 + 2*5^12 + 2*5^13 + 5^14 + 3*5^17 + 2*5^18 + 2*5^19 + O(5^20) >>> y * (-x).artin_hasse_exp() 1 + O(5^20)
The function respects your precision:
sage: x = Zp(3,30)(45/7) sage: x.artin_hasse_exp() 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + 3^13 + 2*3^15 + 2*3^16 + 2*3^17 + 3^19 + 3^20 + 2*3^21 + 3^23 + 3^24 + 3^26 + 3^27 + 2*3^28 + O(3^30)
>>> from sage.all import * >>> x = Zp(Integer(3),Integer(30))(Integer(45)/Integer(7)) >>> x.artin_hasse_exp() 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + 3^13 + 2*3^15 + 2*3^16 + 2*3^17 + 3^19 + 3^20 + 2*3^21 + 3^23 + 3^24 + 3^26 + 3^27 + 2*3^28 + O(3^30)
Unless you tell it not to:
sage: x = Zp(3,30)(45/7) sage: x.artin_hasse_exp() 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + 3^13 + 2*3^15 + 2*3^16 + 2*3^17 + 3^19 + 3^20 + 2*3^21 + 3^23 + 3^24 + 3^26 + 3^27 + 2*3^28 + O(3^30) sage: x.artin_hasse_exp(10) 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + O(3^10)
>>> from sage.all import * >>> x = Zp(Integer(3),Integer(30))(Integer(45)/Integer(7)) >>> x.artin_hasse_exp() 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + 2*3^10 + 3^11 + 3^13 + 2*3^15 + 2*3^16 + 2*3^17 + 3^19 + 3^20 + 2*3^21 + 3^23 + 3^24 + 3^26 + 3^27 + 2*3^28 + O(3^30) >>> x.artin_hasse_exp(Integer(10)) 1 + 2*3^2 + 3^4 + 2*3^5 + 3^6 + 2*3^7 + 2*3^8 + 3^9 + O(3^10)
For precision 1 the function just returns 1 since the exponential is always a 1-unit:
sage: x = Zp(3).random_element() sage: while x.dist(0) >= 1: ....: x = Zp(3).random_element() sage: x.artin_hasse_exp(1) 1 + O(3)
>>> from sage.all import * >>> x = Zp(Integer(3)).random_element() >>> while x.dist(Integer(0)) >= Integer(1): ... x = Zp(Integer(3)).random_element() >>> x.artin_hasse_exp(Integer(1)) 1 + O(3)
AUTHORS:
Mitchell Owen, Sebastian Pancrantz (2012-02): initial version.
Xavier Caruso (2018-08): extend to any p-adic rings and fields and implement several algorithms.
- dwork_expansion(bd=20, a=0)[source]#
Return the value of a function defined by Dwork.
Used to compute the \(p\)-adic Gamma function, see
gamma()
.INPUT:
bd
– integer. Precision bound, defaults to 20a
– integer. Offset parameter, defaults to 0
OUTPUT:
A \(p\)-adic integer.
Note
This is based on GP code written by Fernando Rodriguez Villegas (http://www.ma.utexas.edu/cnt/cnt-frames.html). William Stein sped it up for GP (http://sage.math.washington.edu/home/wstein/www/home/wbhart/pari-2.4.2.alpha/src/basemath/trans2.c). The output is a \(p\)-adic integer from Dwork’s expansion, used to compute the \(p\)-adic gamma function as in [RV2007] section 6.2. The coefficients of the expansion are now cached to speed up multiple evaluation, as in the trace formula for hypergeometric motives.
EXAMPLES:
sage: R = Zp(17) sage: x = R(5+3*17+13*17^2+6*17^3+12*17^5+10*17^(14)+5*17^(17)+O(17^(19))) sage: x.dwork_expansion(18) 16 + 7*17 + 11*17^2 + 4*17^3 + 8*17^4 + 10*17^5 + 11*17^6 + 6*17^7 + 17^8 + 8*17^10 + 13*17^11 + 9*17^12 + 15*17^13 + 2*17^14 + 6*17^15 + 7*17^16 + 6*17^17 + O(17^18) sage: R = Zp(5) sage: x = R(3*5^2+4*5^3+1*5^4+2*5^5+1*5^(10)+O(5^(20))) sage: x.dwork_expansion() 4 + 4*5 + 4*5^2 + 4*5^3 + 2*5^4 + 4*5^5 + 5^7 + 3*5^9 + 4*5^10 + 3*5^11 + 5^13 + 4*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 3*5^18 + O(5^20)
>>> from sage.all import * >>> R = Zp(Integer(17)) >>> x = R(Integer(5)+Integer(3)*Integer(17)+Integer(13)*Integer(17)**Integer(2)+Integer(6)*Integer(17)**Integer(3)+Integer(12)*Integer(17)**Integer(5)+Integer(10)*Integer(17)**(Integer(14))+Integer(5)*Integer(17)**(Integer(17))+O(Integer(17)**(Integer(19)))) >>> x.dwork_expansion(Integer(18)) 16 + 7*17 + 11*17^2 + 4*17^3 + 8*17^4 + 10*17^5 + 11*17^6 + 6*17^7 + 17^8 + 8*17^10 + 13*17^11 + 9*17^12 + 15*17^13 + 2*17^14 + 6*17^15 + 7*17^16 + 6*17^17 + O(17^18) >>> R = Zp(Integer(5)) >>> x = R(Integer(3)*Integer(5)**Integer(2)+Integer(4)*Integer(5)**Integer(3)+Integer(1)*Integer(5)**Integer(4)+Integer(2)*Integer(5)**Integer(5)+Integer(1)*Integer(5)**(Integer(10))+O(Integer(5)**(Integer(20)))) >>> x.dwork_expansion() 4 + 4*5 + 4*5^2 + 4*5^3 + 2*5^4 + 4*5^5 + 5^7 + 3*5^9 + 4*5^10 + 3*5^11 + 5^13 + 4*5^14 + 2*5^15 + 2*5^16 + 2*5^17 + 3*5^18 + O(5^20)
- exp(aprec=None, algorithm=None)[source]#
Compute the \(p\)-adic exponential of this element if the exponential series converges.
INPUT:
aprec
– an integer orNone
(default:None
); if specified, computes only up to the indicated precisionalgorithm
–'generic'
,'binary_splitting'
,'newton'
orNone
(default)The
'generic'
algorithm evaluates naively the series defining the exponential, namely\[\exp(x) = 1 + x + x^2/2 + x^3/6 + x^4/24 + \cdots.\]Its binary complexity is quadratic with respect to the precision.
The
'binary_splitting'
algorithm is faster, it has a quasi-linear complexity.The
'newton'
algorithms solve the equation \(\log(x) =\)self
using a Newton scheme. It runs roughly as fast as the computation of the logarithm.By default, we use the
'binary_splitting'
if it is available. If it is not, we use the'newton'
algorithm if a fast algorithm for computing the logarithm is available. Otherwise we switch to the'generic'
algorithm.
EXAMPLES:
log()
andexp()
are inverse to each other:sage: Z13 = Zp(13, 10) sage: a = Z13(14); a 1 + 13 + O(13^10) sage: a.log().exp() 1 + 13 + O(13^10)
>>> from sage.all import * >>> Z13 = Zp(Integer(13), Integer(10)) >>> a = Z13(Integer(14)); a 1 + 13 + O(13^10) >>> a.log().exp() 1 + 13 + O(13^10)
An error occurs if this is called with an element for which the exponential series does not converge:
sage: Z13.one().exp() Traceback (most recent call last): ... ValueError: Exponential does not converge for that input.
>>> from sage.all import * >>> Z13.one().exp() Traceback (most recent call last): ... ValueError: Exponential does not converge for that input.
The next few examples illustrate precision when computing \(p\)-adic exponentials:
sage: R = Zp(5,10) sage: e = R(2*5 + 2*5**2 + 4*5**3 + 3*5**4 ....: + 5**5 + 3*5**7 + 2*5**8 + 4*5**9).add_bigoh(10); e 2*5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^5 + 3*5^7 + 2*5^8 + 4*5^9 + O(5^10) sage: e.exp()*R.teichmuller(4) 4 + 2*5 + 3*5^3 + O(5^10)
>>> from sage.all import * >>> R = Zp(Integer(5),Integer(10)) >>> e = R(Integer(2)*Integer(5) + Integer(2)*Integer(5)**Integer(2) + Integer(4)*Integer(5)**Integer(3) + Integer(3)*Integer(5)**Integer(4) ... + Integer(5)**Integer(5) + Integer(3)*Integer(5)**Integer(7) + Integer(2)*Integer(5)**Integer(8) + Integer(4)*Integer(5)**Integer(9)).add_bigoh(Integer(10)); e 2*5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^5 + 3*5^7 + 2*5^8 + 4*5^9 + O(5^10) >>> e.exp()*R.teichmuller(Integer(4)) 4 + 2*5 + 3*5^3 + O(5^10)
sage: K = Qp(5,10) sage: e = K(2*5 + 2*5**2 + 4*5**3 + 3*5**4 ....: + 5**5 + 3*5**7 + 2*5**8 + 4*5**9).add_bigoh(10); e 2*5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^5 + 3*5^7 + 2*5^8 + 4*5^9 + O(5^10) sage: e.exp()*K.teichmuller(4) 4 + 2*5 + 3*5^3 + O(5^10)
>>> from sage.all import * >>> K = Qp(Integer(5),Integer(10)) >>> e = K(Integer(2)*Integer(5) + Integer(2)*Integer(5)**Integer(2) + Integer(4)*Integer(5)**Integer(3) + Integer(3)*Integer(5)**Integer(4) ... + Integer(5)**Integer(5) + Integer(3)*Integer(5)**Integer(7) + Integer(2)*Integer(5)**Integer(8) + Integer(4)*Integer(5)**Integer(9)).add_bigoh(Integer(10)); e 2*5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^5 + 3*5^7 + 2*5^8 + 4*5^9 + O(5^10) >>> e.exp()*K.teichmuller(Integer(4)) 4 + 2*5 + 3*5^3 + O(5^10)
Logarithms and exponentials in extension fields. First, in an Eisenstein extension:
sage: # needs sage.libs.ntl sage: R = Zp(5,5) sage: S.<x> = R[] sage: f = x^4 + 15*x^2 + 625*x - 5 sage: W.<w> = R.ext(f) sage: z = 1 + w^2 + 4*w^7; z 1 + w^2 + 4*w^7 + O(w^20) sage: z.log().exp() 1 + w^2 + 4*w^7 + O(w^20)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> R = Zp(Integer(5),Integer(5)) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(4) + Integer(15)*x**Integer(2) + Integer(625)*x - Integer(5) >>> W = R.ext(f, names=('w',)); (w,) = W._first_ngens(1) >>> z = Integer(1) + w**Integer(2) + Integer(4)*w**Integer(7); z 1 + w^2 + 4*w^7 + O(w^20) >>> z.log().exp() 1 + w^2 + 4*w^7 + O(w^20)
Now an unramified example:
sage: # needs sage.libs.ntl sage: R = Zp(5,5) sage: S.<x> = R[] sage: g = x^3 + 3*x + 3 sage: A.<a> = R.ext(g) sage: b = 1 + 5*(1 + a^2) + 5^3*(3 + 2*a); b 1 + (a^2 + 1)*5 + (2*a + 3)*5^3 + O(5^5) sage: b.log().exp() 1 + (a^2 + 1)*5 + (2*a + 3)*5^3 + O(5^5)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> R = Zp(Integer(5),Integer(5)) >>> S = R['x']; (x,) = S._first_ngens(1) >>> g = x**Integer(3) + Integer(3)*x + Integer(3) >>> A = R.ext(g, names=('a',)); (a,) = A._first_ngens(1) >>> b = Integer(1) + Integer(5)*(Integer(1) + a**Integer(2)) + Integer(5)**Integer(3)*(Integer(3) + Integer(2)*a); b 1 + (a^2 + 1)*5 + (2*a + 3)*5^3 + O(5^5) >>> b.log().exp() 1 + (a^2 + 1)*5 + (2*a + 3)*5^3 + O(5^5)
AUTHORS:
Genya Zaytman (2007-02-15)
Amnon Besser, Marc Masdeu (2012-02-23): Complete rewrite
Julian Rueth (2013-02-14): Added doctests, fixed some corner cases
Xavier Caruso (2017-06): Added binary splitting and Newton algorithms
- gamma(algorithm='pari')[source]#
Return the value of the \(p\)-adic Gamma function.
INPUT:
algorithm
– string. Can be set to'pari'
to call the PARI function, or'sage'
to call the function implemented in Sage. The default is'pari'
since PARI is about 10 times faster than Sage.
OUTPUT:
a \(p\)-adic integer
Note
This is based on GP code written by Fernando Rodriguez Villegas (http://www.ma.utexas.edu/cnt/cnt-frames.html). William Stein sped it up for GP (http://sage.math.washington.edu/home/wstein/www/home/wbhart/pari-2.4.2.alpha/src/basemath/trans2.c). The
'sage'
version uses dwork_expansion() to compute the \(p\)-adic gamma function of self as in [RV2007] section 6.2.EXAMPLES:
This example illustrates
x.gamma()
for \(x\) a \(p\)-adic unit:sage: R = Zp(7) sage: x = R(2+3*7^2+4*7^3+O(7^20)) sage: x.gamma('pari') 1 + 2*7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^8 + 7^9 + 4*7^10 + 3*7^12 + 7^13 + 5*7^14 + 3*7^15 + 2*7^16 + 2*7^17 + 5*7^18 + 4*7^19 + O(7^20) sage: x.gamma('sage') 1 + 2*7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^8 + 7^9 + 4*7^10 + 3*7^12 + 7^13 + 5*7^14 + 3*7^15 + 2*7^16 + 2*7^17 + 5*7^18 + 4*7^19 + O(7^20) sage: x.gamma('pari') == x.gamma('sage') True
>>> from sage.all import * >>> R = Zp(Integer(7)) >>> x = R(Integer(2)+Integer(3)*Integer(7)**Integer(2)+Integer(4)*Integer(7)**Integer(3)+O(Integer(7)**Integer(20))) >>> x.gamma('pari') 1 + 2*7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^8 + 7^9 + 4*7^10 + 3*7^12 + 7^13 + 5*7^14 + 3*7^15 + 2*7^16 + 2*7^17 + 5*7^18 + 4*7^19 + O(7^20) >>> x.gamma('sage') 1 + 2*7^2 + 4*7^3 + 5*7^4 + 3*7^5 + 7^8 + 7^9 + 4*7^10 + 3*7^12 + 7^13 + 5*7^14 + 3*7^15 + 2*7^16 + 2*7^17 + 5*7^18 + 4*7^19 + O(7^20) >>> x.gamma('pari') == x.gamma('sage') True
Now
x.gamma()
for \(x\) a \(p\)-adic integer but not a unit:sage: R = Zp(17) sage: x = R(17+17^2+3*17^3+12*17^8+O(17^13)) sage: x.gamma('pari') 1 + 12*17 + 13*17^2 + 13*17^3 + 10*17^4 + 7*17^5 + 16*17^7 + 13*17^9 + 4*17^10 + 9*17^11 + 17^12 + O(17^13) sage: x.gamma('sage') 1 + 12*17 + 13*17^2 + 13*17^3 + 10*17^4 + 7*17^5 + 16*17^7 + 13*17^9 + 4*17^10 + 9*17^11 + 17^12 + O(17^13) sage: x.gamma('pari') == x.gamma('sage') True
>>> from sage.all import * >>> R = Zp(Integer(17)) >>> x = R(Integer(17)+Integer(17)**Integer(2)+Integer(3)*Integer(17)**Integer(3)+Integer(12)*Integer(17)**Integer(8)+O(Integer(17)**Integer(13))) >>> x.gamma('pari') 1 + 12*17 + 13*17^2 + 13*17^3 + 10*17^4 + 7*17^5 + 16*17^7 + 13*17^9 + 4*17^10 + 9*17^11 + 17^12 + O(17^13) >>> x.gamma('sage') 1 + 12*17 + 13*17^2 + 13*17^3 + 10*17^4 + 7*17^5 + 16*17^7 + 13*17^9 + 4*17^10 + 9*17^11 + 17^12 + O(17^13) >>> x.gamma('pari') == x.gamma('sage') True
Finally, this function is not defined if \(x\) is not a \(p\)-adic integer:
sage: K = Qp(7) sage: x = K(7^-5 + 2*7^-4 + 5*7^-3 + 2*7^-2 + 3*7^-1 + 3 + 3*7 ....: + 7^3 + 4*7^4 + 5*7^5 + 6*7^8 + 3*7^9 + 6*7^10 + 5*7^11 + 6*7^12 ....: + 3*7^13 + 5*7^14 + O(7^15)) sage: x.gamma() Traceback (most recent call last): ... ValueError: The p-adic gamma function only works on elements of Zp
>>> from sage.all import * >>> K = Qp(Integer(7)) >>> x = K(Integer(7)**-Integer(5) + Integer(2)*Integer(7)**-Integer(4) + Integer(5)*Integer(7)**-Integer(3) + Integer(2)*Integer(7)**-Integer(2) + Integer(3)*Integer(7)**-Integer(1) + Integer(3) + Integer(3)*Integer(7) ... + Integer(7)**Integer(3) + Integer(4)*Integer(7)**Integer(4) + Integer(5)*Integer(7)**Integer(5) + Integer(6)*Integer(7)**Integer(8) + Integer(3)*Integer(7)**Integer(9) + Integer(6)*Integer(7)**Integer(10) + Integer(5)*Integer(7)**Integer(11) + Integer(6)*Integer(7)**Integer(12) ... + Integer(3)*Integer(7)**Integer(13) + Integer(5)*Integer(7)**Integer(14) + O(Integer(7)**Integer(15))) >>> x.gamma() Traceback (most recent call last): ... ValueError: The p-adic gamma function only works on elements of Zp
- gcd(other)[source]#
Return a greatest common divisor of
self
andother
.INPUT:
other
– an element in the same ring asself
AUTHORS:
Julian Rueth (2012-10-19): initial version
Note
Since the elements are only given with finite precision, their greatest common divisor is in general not unique (not even up to units). For example \(O(3)\) is a representative for the elements 0 and 3 in the 3-adic ring \(\ZZ_3\). The greatest common divisor of \(O(3)\) and \(O(3)\) could be (among others) 3 or 0 which have different valuation. The algorithm implemented here, will return an element of minimal valuation among the possible greatest common divisors.
EXAMPLES:
The greatest common divisor is either zero or a power of the uniformizing parameter:
sage: R = Zp(3) sage: R.zero().gcd(R.zero()) 0 sage: R(3).gcd(9) 3 + O(3^21)
>>> from sage.all import * >>> R = Zp(Integer(3)) >>> R.zero().gcd(R.zero()) 0 >>> R(Integer(3)).gcd(Integer(9)) 3 + O(3^21)
A non-zero result is always lifted to the maximal precision possible in the ring:
sage: a = R(3,2); a 3 + O(3^2) sage: b = R(9,3); b 3^2 + O(3^3) sage: a.gcd(b) 3 + O(3^21) sage: a.gcd(0) 3 + O(3^21)
>>> from sage.all import * >>> a = R(Integer(3),Integer(2)); a 3 + O(3^2) >>> b = R(Integer(9),Integer(3)); b 3^2 + O(3^3) >>> a.gcd(b) 3 + O(3^21) >>> a.gcd(Integer(0)) 3 + O(3^21)
If both elements are zero, then the result is zero with the precision set to the smallest of their precisions:
sage: a = R.zero(); a 0 sage: b = R(0,2); b O(3^2) sage: a.gcd(b) O(3^2)
>>> from sage.all import * >>> a = R.zero(); a 0 >>> b = R(Integer(0),Integer(2)); b O(3^2) >>> a.gcd(b) O(3^2)
One could argue that it is mathematically correct to return \(9 + O(3^{22})\) instead. However, this would lead to some confusing behaviour:
sage: alternative_gcd = R(9,22); alternative_gcd 3^2 + O(3^22) sage: a.is_zero() True sage: b.is_zero() True sage: alternative_gcd.is_zero() False
>>> from sage.all import * >>> alternative_gcd = R(Integer(9),Integer(22)); alternative_gcd 3^2 + O(3^22) >>> a.is_zero() True >>> b.is_zero() True >>> alternative_gcd.is_zero() False
If exactly one element is zero, then the result depends on the valuation of the other element:
sage: R(0,3).gcd(3^4) O(3^3) sage: R(0,4).gcd(3^4) O(3^4) sage: R(0,5).gcd(3^4) 3^4 + O(3^24)
>>> from sage.all import * >>> R(Integer(0),Integer(3)).gcd(Integer(3)**Integer(4)) O(3^3) >>> R(Integer(0),Integer(4)).gcd(Integer(3)**Integer(4)) O(3^4) >>> R(Integer(0),Integer(5)).gcd(Integer(3)**Integer(4)) 3^4 + O(3^24)
Over a field, the greatest common divisor is either zero (possibly with finite precision) or one:
sage: K = Qp(3) sage: K(3).gcd(0) 1 + O(3^20) sage: K.zero().gcd(0) 0 sage: K.zero().gcd(K(0,2)) O(3^2) sage: K(3).gcd(4) 1 + O(3^20)
>>> from sage.all import * >>> K = Qp(Integer(3)) >>> K(Integer(3)).gcd(Integer(0)) 1 + O(3^20) >>> K.zero().gcd(Integer(0)) 0 >>> K.zero().gcd(K(Integer(0),Integer(2))) O(3^2) >>> K(Integer(3)).gcd(Integer(4)) 1 + O(3^20)
- is_prime()[source]#
Return whether this element is prime in its parent.
EXAMPLES:
sage: A = Zp(2) sage: A(1).is_prime() False sage: A(2).is_prime() True sage: K = A.fraction_field() sage: K(2).is_prime() False
>>> from sage.all import * >>> A = Zp(Integer(2)) >>> A(Integer(1)).is_prime() False >>> A(Integer(2)).is_prime() True >>> K = A.fraction_field() >>> K(Integer(2)).is_prime() False
sage: # needs sage.libs.ntl sage: x = polygen(ZZ, 'x') sage: B.<pi> = A.extension(x^5 - 2) sage: pi.is_prime() # needs sage.symbolic True sage: B(2).is_prime() False
>>> from sage.all import * >>> # needs sage.libs.ntl >>> x = polygen(ZZ, 'x') >>> B = A.extension(x**Integer(5) - Integer(2), names=('pi',)); (pi,) = B._first_ngens(1) >>> pi.is_prime() # needs sage.symbolic True >>> B(Integer(2)).is_prime() False
- is_square()[source]#
Returns whether this element is a square
INPUT:
self
– a \(p\)-adic element
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
>>> from sage.all import * >>> R = Zp(Integer(3),Integer(20),'capped-rel') >>> R(Integer(0)).is_square() True >>> R(Integer(1)).is_square() True >>> R(Integer(2)).is_square() False
- is_squarefree()[source]#
Return whether this element is squarefree, i.e., whether there exists no non-unit \(g\) such that \(g^2\) divides this element.
EXAMPLES:
The zero element is never squarefree:
sage: K = Qp(2) sage: K.zero().is_squarefree() False
>>> from sage.all import * >>> K = Qp(Integer(2)) >>> K.zero().is_squarefree() False
In \(p\)-adic rings, only elements of valuation at most 1 are squarefree:
sage: R = Zp(2) sage: R(1).is_squarefree() True sage: R(2).is_squarefree() True sage: R(4).is_squarefree() False
>>> from sage.all import * >>> R = Zp(Integer(2)) >>> R(Integer(1)).is_squarefree() True >>> R(Integer(2)).is_squarefree() True >>> R(Integer(4)).is_squarefree() False
This works only if the precision is known sufficiently well:
sage: R(0,1).is_squarefree() Traceback (most recent call last): ... PrecisionError: element not known to sufficient precision to decide squarefreeness sage: R(0,2).is_squarefree() False sage: R(1,1).is_squarefree() True
>>> from sage.all import * >>> R(Integer(0),Integer(1)).is_squarefree() Traceback (most recent call last): ... PrecisionError: element not known to sufficient precision to decide squarefreeness >>> R(Integer(0),Integer(2)).is_squarefree() False >>> R(Integer(1),Integer(1)).is_squarefree() True
For fields we are not so strict about the precision and treat inexact zeros as the zero element:
K(0,0).is_squarefree() False
- log(p_branch=None, pi_branch=None, aprec=None, change_frac=False, algorithm=None)[source]#
Compute the \(p\)-adic logarithm of this element.
The usual power series for the logarithm with values in the additive group of a \(p\)-adic ring only converges for 1-units (units congruent to 1 modulo \(p\)). However, there is a unique extension of the logarithm to a homomorphism defined on all the units: If \(u = a \cdot v\) is a unit with \(v \equiv 1 \pmod{p}\) and \(a\) a Teichmuller representative, then we define \(log(u) = log(v)\). This is the correct extension because the units \(U\) split as a product \(U = V \times \langle w \rangle\), where \(V\) is the subgroup of 1-units and \(w\) is a fundamental root of unity. The \(\langle w \rangle\) factor is torsion, so must go to 0 under any homomorphism to the fraction field, which is a torsion free group.
INPUT:
p_branch
– an element in the base ring or its fraction field; the implementation will choose the branch of the logarithm which sends \(p\) tobranch
pi_branch
– an element in the base ring or its fraction field; the implementation will choose the branch of the logarithm which sends the uniformizer tobranch
; you may specify at most one ofp_branch
andpi_branch
, and must specify one of them if this element is not a unitaprec
– an integer orNone
(default:None
); if notNone
, then the result will only be correct to precisionaprec
change_frac
– In general the codomain of the logarithm should be in the \(p\)-adic field, however, for most neighborhoods of 1, it lies in the ring of integers. This flag decides if the codomain should be the same as the input (default) or if it should change to the fraction field of the input.algorithm
–'generic'
,'binary_splitting'
orNone
(default) The generic algorithm evaluates naively the series defining the log, namely\[\log(1-x) = -x - 1/2 x^2 - 1/3 x^3 - 1/4 x^4 - 1/5 x^5 - \cdots.\]Its binary complexity is quadratic with respect to the precision.
The
'binary_splitting'
algorithm is faster, it has a quasi-linear complexity. By default, we use'binary_splitting'
if it is available. Otherwise we switch to the'generic'
algorithm.
Note
What some other systems do:
PARI: Seems to define the logarithm for units not congruent to 1 as we do.
MAGMA: Only implements logarithm for 1-units (version 2.19-2)
Todo
There is a soft-linear time algorithm for logarithm described by Dan Bernstein at http://cr.yp.to/lineartime/multapps-20041007.pdf
EXAMPLES:
sage: Z13 = Zp(13, 10) sage: a = Z13(14); a 1 + 13 + O(13^10) sage: a.log() 13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10) sage: Q13 = Qp(13, 10) sage: a = Q13(14); a 1 + 13 + O(13^10) sage: a.log() 13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10)
>>> from sage.all import * >>> Z13 = Zp(Integer(13), Integer(10)) >>> a = Z13(Integer(14)); a 1 + 13 + O(13^10) >>> a.log() 13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10) >>> Q13 = Qp(Integer(13), Integer(10)) >>> a = Q13(Integer(14)); a 1 + 13 + O(13^10) >>> a.log() 13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10)
Note that the relative precision decreases when we take log. Precisely the absolute precision on
log(a)
agrees with the relative precision ona
thanks to the relation \(d\log(a) = da/a\).The call
log(a)
works as well:sage: log(a) 13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10) sage: log(a) == a.log() True
>>> from sage.all import * >>> log(a) 13 + 6*13^2 + 2*13^3 + 5*13^4 + 10*13^6 + 13^7 + 11*13^8 + 8*13^9 + O(13^10) >>> log(a) == a.log() True
The logarithm is not only defined for 1-units:
sage: R = Zp(5,10) sage: a = R(2) sage: a.log() 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
>>> from sage.all import * >>> R = Zp(Integer(5),Integer(10)) >>> a = R(Integer(2)) >>> a.log() 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
If you want to take the logarithm of a non-unit you must specify either
p_branch
orpi_branch
:sage: b = R(5) sage: b.log() Traceback (most recent call last): ... ValueError: you must specify a branch of the logarithm for non-units sage: b.log(p_branch=4) 4 + O(5^10) sage: c = R(10) sage: c.log(p_branch=4) 4 + 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
>>> from sage.all import * >>> b = R(Integer(5)) >>> b.log() Traceback (most recent call last): ... ValueError: you must specify a branch of the logarithm for non-units >>> b.log(p_branch=Integer(4)) 4 + O(5^10) >>> c = R(Integer(10)) >>> c.log(p_branch=Integer(4)) 4 + 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
The branch parameters are only relevant for elements of non-zero valuation:
sage: a.log(p_branch=0) 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10) sage: a.log(p_branch=1) 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
>>> from sage.all import * >>> a.log(p_branch=Integer(0)) 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10) >>> a.log(p_branch=Integer(1)) 2*5 + 3*5^2 + 2*5^3 + 4*5^4 + 2*5^6 + 2*5^7 + 4*5^8 + 2*5^9 + O(5^10)
Logarithms can also be computed in extension fields. First, in an Eisenstein extension:
sage: R = Zp(5,5) sage: S.<x> = ZZ[] sage: f = x^4 + 15*x^2 + 625*x - 5 sage: W.<w> = R.ext(f) # needs sage.libs.ntl sage: z = 1 + w^2 + 4*w^7; z # needs sage.libs.ntl 1 + w^2 + 4*w^7 + O(w^20) sage: z.log() # needs sage.libs.ntl w^2 + 2*w^4 + 3*w^6 + 4*w^7 + w^9 + 4*w^10 + 4*w^11 + 4*w^12 + 3*w^14 + w^15 + w^17 + 3*w^18 + 3*w^19 + O(w^20)
>>> from sage.all import * >>> R = Zp(Integer(5),Integer(5)) >>> S = ZZ['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(4) + Integer(15)*x**Integer(2) + Integer(625)*x - Integer(5) >>> W = R.ext(f, names=('w',)); (w,) = W._first_ngens(1)# needs sage.libs.ntl >>> z = Integer(1) + w**Integer(2) + Integer(4)*w**Integer(7); z # needs sage.libs.ntl 1 + w^2 + 4*w^7 + O(w^20) >>> z.log() # needs sage.libs.ntl w^2 + 2*w^4 + 3*w^6 + 4*w^7 + w^9 + 4*w^10 + 4*w^11 + 4*w^12 + 3*w^14 + w^15 + w^17 + 3*w^18 + 3*w^19 + O(w^20)
In an extension, there will usually be a difference between specifying
p_branch
andpi_branch
:sage: # needs sage.libs.ntl sage: b = W(5) sage: b.log() Traceback (most recent call last): ... ValueError: you must specify a branch of the logarithm for non-units sage: b.log(p_branch=0) O(w^20) sage: b.log(p_branch=w) w + O(w^20) sage: b.log(pi_branch=0) 3*w^2 + 2*w^4 + 2*w^6 + 3*w^8 + 4*w^10 + w^13 + w^14 + 2*w^15 + 2*w^16 + w^18 + 4*w^19 + O(w^20) sage: b.unit_part().log() 3*w^2 + 2*w^4 + 2*w^6 + 3*w^8 + 4*w^10 + w^13 + w^14 + 2*w^15 + 2*w^16 + w^18 + 4*w^19 + O(w^20) sage: y = w^2 * 4*w^7; y 4*w^9 + O(w^29) sage: y.log(p_branch=0) 2*w^2 + 2*w^4 + 2*w^6 + 2*w^8 + w^10 + w^12 + 4*w^13 + 4*w^14 + 3*w^15 + 4*w^16 + 4*w^17 + w^18 + 4*w^19 + O(w^20) sage: y.log(p_branch=w) w + 2*w^2 + 2*w^4 + 4*w^5 + 2*w^6 + 2*w^7 + 2*w^8 + 4*w^9 + w^10 + 3*w^11 + w^12 + 4*w^14 + 4*w^16 + 2*w^17 + w^19 + O(w^20)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> b = W(Integer(5)) >>> b.log() Traceback (most recent call last): ... ValueError: you must specify a branch of the logarithm for non-units >>> b.log(p_branch=Integer(0)) O(w^20) >>> b.log(p_branch=w) w + O(w^20) >>> b.log(pi_branch=Integer(0)) 3*w^2 + 2*w^4 + 2*w^6 + 3*w^8 + 4*w^10 + w^13 + w^14 + 2*w^15 + 2*w^16 + w^18 + 4*w^19 + O(w^20) >>> b.unit_part().log() 3*w^2 + 2*w^4 + 2*w^6 + 3*w^8 + 4*w^10 + w^13 + w^14 + 2*w^15 + 2*w^16 + w^18 + 4*w^19 + O(w^20) >>> y = w**Integer(2) * Integer(4)*w**Integer(7); y 4*w^9 + O(w^29) >>> y.log(p_branch=Integer(0)) 2*w^2 + 2*w^4 + 2*w^6 + 2*w^8 + w^10 + w^12 + 4*w^13 + 4*w^14 + 3*w^15 + 4*w^16 + 4*w^17 + w^18 + 4*w^19 + O(w^20) >>> y.log(p_branch=w) w + 2*w^2 + 2*w^4 + 4*w^5 + 2*w^6 + 2*w^7 + 2*w^8 + 4*w^9 + w^10 + 3*w^11 + w^12 + 4*w^14 + 4*w^16 + 2*w^17 + w^19 + O(w^20)
Check that log is multiplicative:
sage: y.log(p_branch=0) + z.log() - (y*z).log(p_branch=0) # needs sage.libs.ntl O(w^20)
>>> from sage.all import * >>> y.log(p_branch=Integer(0)) + z.log() - (y*z).log(p_branch=Integer(0)) # needs sage.libs.ntl O(w^20)
Now an unramified example:
sage: # needs sage.libs.ntl sage: g = x^3 + 3*x + 3 sage: A.<a> = R.ext(g) sage: b = 1 + 5*(1 + a^2) + 5^3*(3 + 2*a) sage: b.log() (a^2 + 1)*5 + (3*a^2 + 4*a + 2)*5^2 + (3*a^2 + 2*a)*5^3 + (3*a^2 + 2*a + 2)*5^4 + O(5^5)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> g = x**Integer(3) + Integer(3)*x + Integer(3) >>> A = R.ext(g, names=('a',)); (a,) = A._first_ngens(1) >>> b = Integer(1) + Integer(5)*(Integer(1) + a**Integer(2)) + Integer(5)**Integer(3)*(Integer(3) + Integer(2)*a) >>> b.log() (a^2 + 1)*5 + (3*a^2 + 4*a + 2)*5^2 + (3*a^2 + 2*a)*5^3 + (3*a^2 + 2*a + 2)*5^4 + O(5^5)
Check that log is multiplicative:
sage: # needs sage.libs.ntl sage: c = 3 + 5^2*(2 + 4*a) sage: b.log() + c.log() - (b*c).log() O(5^5)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> c = Integer(3) + Integer(5)**Integer(2)*(Integer(2) + Integer(4)*a) >>> b.log() + c.log() - (b*c).log() O(5^5)
We illustrate the effect of the
precision
argument:sage: R = ZpCA(7,10) sage: x = R(41152263); x 5 + 3*7^2 + 4*7^3 + 3*7^4 + 5*7^5 + 6*7^6 + 7^9 + O(7^10) sage: x.log(aprec = 5) 7 + 3*7^2 + 4*7^3 + 3*7^4 + O(7^5) sage: x.log(aprec = 7) 7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + O(7^7) sage: x.log() 7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + 7^7 + 3*7^8 + 4*7^9 + O(7^10)
>>> from sage.all import * >>> R = ZpCA(Integer(7),Integer(10)) >>> x = R(Integer(41152263)); x 5 + 3*7^2 + 4*7^3 + 3*7^4 + 5*7^5 + 6*7^6 + 7^9 + O(7^10) >>> x.log(aprec = Integer(5)) 7 + 3*7^2 + 4*7^3 + 3*7^4 + O(7^5) >>> x.log(aprec = Integer(7)) 7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + O(7^7) >>> x.log() 7 + 3*7^2 + 4*7^3 + 3*7^4 + 7^5 + 3*7^6 + 7^7 + 3*7^8 + 4*7^9 + O(7^10)
The logarithm is not defined for zero:
sage: R.zero().log() Traceback (most recent call last): ... ValueError: logarithm is not defined at zero
>>> from sage.all import * >>> R.zero().log() Traceback (most recent call last): ... ValueError: logarithm is not defined at zero
For elements in a \(p\)-adic ring, the logarithm will be returned in the same ring:
sage: x = R(2) sage: x.log().parent() 7-adic Ring with capped absolute precision 10 sage: x = R(14) sage: x.log(p_branch=0).parent() 7-adic Ring with capped absolute precision 10
>>> from sage.all import * >>> x = R(Integer(2)) >>> x.log().parent() 7-adic Ring with capped absolute precision 10 >>> x = R(Integer(14)) >>> x.log(p_branch=Integer(0)).parent() 7-adic Ring with capped absolute precision 10
This is not possible if the logarithm has negative valuation:
sage: R = ZpCA(3,10) sage: S.<x> = R[] sage: f = x^3 - 3 sage: W.<w> = R.ext(f) # needs sage.libs.ntl sage.rings.padics sage: w.log(p_branch=2) # needs sage.libs.ntl sage.rings.padics Traceback (most recent call last): ... ValueError: logarithm is not integral, use change_frac=True to obtain a result in the fraction field sage: w.log(p_branch=2, change_frac=True) # needs sage.libs.ntl sage.rings.padics 2*w^-3 + O(w^24)
>>> from sage.all import * >>> R = ZpCA(Integer(3),Integer(10)) >>> S = R['x']; (x,) = S._first_ngens(1) >>> f = x**Integer(3) - Integer(3) >>> W = R.ext(f, names=('w',)); (w,) = W._first_ngens(1)# needs sage.libs.ntl sage.rings.padics >>> w.log(p_branch=Integer(2)) # needs sage.libs.ntl sage.rings.padics Traceback (most recent call last): ... ValueError: logarithm is not integral, use change_frac=True to obtain a result in the fraction field >>> w.log(p_branch=Integer(2), change_frac=True) # needs sage.libs.ntl sage.rings.padics 2*w^-3 + O(w^24)
AUTHORS:
William Stein: initial version
David Harvey (2006-09-13): corrected subtle precision bug (need to take denominators into account! – see Issue #53)
Genya Zaytman (2007-02-14): adapted to new \(p\)-adic class
Amnon Besser, Marc Masdeu (2012-02-21): complete rewrite, valid for generic \(p\)-adic rings.
Soroosh Yazdani (2013-02-1): Fixed a precision issue in
_log_generic()
. This should really fix the issue with divisions.Julian Rueth (2013-02-14): Added doctests, some changes for capped-absolute implementations.
Xavier Caruso (2017-06): Added binary splitting type algorithms over Qp
- minimal_polynomial(name='x', base=None)[source]#
Returns the minimal polynomial of this element over
base
INPUT:
name
– string (default:'x'
): the name of the variablebase
– a ring (default: the base ring of the parent): the base ring over which the minimal polynomial is computed
EXAMPLES:
sage: Zp(5,5)(1/3).minimal_polynomial('x') # needs sage.libs.ntl (1 + O(5^5))*x + 3 + 5 + 3*5^2 + 5^3 + 3*5^4 + O(5^5) sage: Zp(5,5)(1/3).minimal_polynomial('foo') # needs sage.libs.ntl (1 + O(5^5))*foo + 3 + 5 + 3*5^2 + 5^3 + 3*5^4 + O(5^5)
>>> from sage.all import * >>> Zp(Integer(5),Integer(5))(Integer(1)/Integer(3)).minimal_polynomial('x') # needs sage.libs.ntl (1 + O(5^5))*x + 3 + 5 + 3*5^2 + 5^3 + 3*5^4 + O(5^5) >>> Zp(Integer(5),Integer(5))(Integer(1)/Integer(3)).minimal_polynomial('foo') # needs sage.libs.ntl (1 + O(5^5))*foo + 3 + 5 + 3*5^2 + 5^3 + 3*5^4 + O(5^5)
sage: # needs sage.libs.ntl sage: K.<a> = QqCR(2^3,5) sage: S.<x> = K[] sage: L.<pi> = K.extension(x^4 - 2*a) sage: pi.minimal_polynomial() # needs sage.symbolic (1 + O(2^5))*x^4 + a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6) sage: (pi^2).minimal_polynomial() # needs sage.symbolic (1 + O(2^5))*x^2 + a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6) sage: (1/pi).minimal_polynomial() # needs sage.symbolic (1 + O(2^5))*x^4 + (a^2 + 1)*2^-1 + O(2^4) sage: elt = L.random_element() sage: P = elt.minimal_polynomial() # not tested, known bug (see :issue:`32111`) sage: P(elt) == 0 # not tested True
>>> from sage.all import * >>> # needs sage.libs.ntl >>> K = QqCR(Integer(2)**Integer(3),Integer(5), names=('a',)); (a,) = K._first_ngens(1) >>> S = K['x']; (x,) = S._first_ngens(1) >>> L = K.extension(x**Integer(4) - Integer(2)*a, names=('pi',)); (pi,) = L._first_ngens(1) >>> pi.minimal_polynomial() # needs sage.symbolic (1 + O(2^5))*x^4 + a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6) >>> (pi**Integer(2)).minimal_polynomial() # needs sage.symbolic (1 + O(2^5))*x^2 + a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6) >>> (Integer(1)/pi).minimal_polynomial() # needs sage.symbolic (1 + O(2^5))*x^4 + (a^2 + 1)*2^-1 + O(2^4) >>> elt = L.random_element() >>> P = elt.minimal_polynomial() # not tested, known bug (see :issue:`32111`) >>> P(elt) == Integer(0) # not tested True
- multiplicative_order(prec=None)[source]#
Returns the multiplicative order of
self
, whereself
is considered to be one if it is one modulo \(p^{\mbox{prec}}\).INPUT:
self
– a \(p\)-adic elementprec
– 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(5).multiplicative_order(20) +Infinity sage: K(1/5).multiplicative_order(20) +Infinity sage: K.zeta().multiplicative_order(20) 4
>>> from sage.all import * >>> K = Qp(Integer(5),Integer(20),'capped-rel') >>> K(-Integer(1)).multiplicative_order(Integer(20)) 2 >>> K(Integer(1)).multiplicative_order(Integer(20)) 1 >>> K(Integer(2)).multiplicative_order(Integer(20)) +Infinity >>> K(Integer(5)).multiplicative_order(Integer(20)) +Infinity >>> K(Integer(1)/Integer(5)).multiplicative_order(Integer(20)) +Infinity >>> K.zeta().multiplicative_order(Integer(20)) 4
Over unramified extensions:
sage: # needs sage.libs.ntl sage: L1.<a> = Qq(5^3) sage: c = L1.teichmuller(a) sage: c.multiplicative_order() 124 sage: c^124 1 + O(5^20)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> L1 = Qq(Integer(5)**Integer(3), names=('a',)); (a,) = L1._first_ngens(1) >>> c = L1.teichmuller(a) >>> c.multiplicative_order() 124 >>> c**Integer(124) 1 + O(5^20)
Over totally ramified extensions:
sage: # needs sage.libs.ntl sage: x = polygen(ZZ, 'x') sage: L2.<pi> = Qp(5).extension(x^4 + 5*x^3 + 10*x^2 + 10*x + 5) sage: u = 1 + pi sage: u.multiplicative_order() 5 sage: v = L2.teichmuller(2) sage: v.multiplicative_order() 4 sage: (u*v).multiplicative_order() 20
>>> from sage.all import * >>> # needs sage.libs.ntl >>> x = polygen(ZZ, 'x') >>> L2 = Qp(Integer(5)).extension(x**Integer(4) + Integer(5)*x**Integer(3) + Integer(10)*x**Integer(2) + Integer(10)*x + Integer(5), names=('pi',)); (pi,) = L2._first_ngens(1) >>> u = Integer(1) + pi >>> u.multiplicative_order() 5 >>> v = L2.teichmuller(Integer(2)) >>> v.multiplicative_order() 4 >>> (u*v).multiplicative_order() 20
- norm(base=None)[source]#
Return the norm of this \(p\)-adic element over
base
.Warning
This is not the \(p\)-adic absolute value. This is a field theoretic norm down to a base ring. If you want the \(p\)-adic absolute value, use the method
abs()
instead.INPUT:
base
– a subring of the parent (default: base ring)
OUTPUT:
The norm of this \(p\)-adic element over the given base.
EXAMPLES:
sage: Zp(5)(5).norm() # needs sage.libs.ntl 5 + O(5^21)
>>> from sage.all import * >>> Zp(Integer(5))(Integer(5)).norm() # needs sage.libs.ntl 5 + O(5^21)
sage: # needs sage.libs.ntl sage: K.<a> = QqCR(2^3,5) sage: S.<x> = K[] sage: L.<pi> = K.extension(x^4 - 2*a) sage: pi.norm() # norm over K # needs sage.symbolic a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6) sage: (pi^2).norm() # needs sage.symbolic a^2*2^2 + O(2^7) sage: pi.norm()^2 # needs sage.symbolic a^2*2^2 + O(2^7)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> K = QqCR(Integer(2)**Integer(3),Integer(5), names=('a',)); (a,) = K._first_ngens(1) >>> S = K['x']; (x,) = S._first_ngens(1) >>> L = K.extension(x**Integer(4) - Integer(2)*a, names=('pi',)); (pi,) = L._first_ngens(1) >>> pi.norm() # norm over K # needs sage.symbolic a*2 + a*2^2 + a*2^3 + a*2^4 + a*2^5 + O(2^6) >>> (pi**Integer(2)).norm() # needs sage.symbolic a^2*2^2 + O(2^7) >>> pi.norm()**Integer(2) # needs sage.symbolic a^2*2^2 + O(2^7)
- nth_root(n, all=False)[source]#
Return the \(n\)-th root of this element.
INPUT:
n
– an integerall
– a boolean (default:False
): ifTrue
, return all \(n\)-th roots of this element, instead of just one.
EXAMPLES:
sage: A = Zp(5,10) sage: x = A(61376); x 1 + 5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^10) sage: y = x.nth_root(4); y 2 + 5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^6 + O(5^10) sage: y^4 == x True sage: x.nth_root(4, all=True) [2 + 5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^6 + O(5^10), 4 + 4*5 + 4*5^2 + 4*5^4 + 3*5^5 + 5^6 + 3*5^7 + 5^8 + 5^9 + O(5^10), 3 + 3*5 + 2*5^2 + 5^4 + 4*5^5 + 3*5^6 + 4*5^7 + 4*5^8 + 4*5^9 + O(5^10), 1 + 4*5^3 + 5^5 + 3*5^6 + 5^7 + 3*5^8 + 3*5^9 + O(5^10)]
>>> from sage.all import * >>> A = Zp(Integer(5),Integer(10)) >>> x = A(Integer(61376)); x 1 + 5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^10) >>> y = x.nth_root(Integer(4)); y 2 + 5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^6 + O(5^10) >>> y**Integer(4) == x True >>> x.nth_root(Integer(4), all=True) [2 + 5 + 2*5^2 + 4*5^3 + 3*5^4 + 5^6 + O(5^10), 4 + 4*5 + 4*5^2 + 4*5^4 + 3*5^5 + 5^6 + 3*5^7 + 5^8 + 5^9 + O(5^10), 3 + 3*5 + 2*5^2 + 5^4 + 4*5^5 + 3*5^6 + 4*5^7 + 4*5^8 + 4*5^9 + O(5^10), 1 + 4*5^3 + 5^5 + 3*5^6 + 5^7 + 3*5^8 + 3*5^9 + O(5^10)]
When \(n\) is divisible by the underlying prime \(p\), we are losing precision (which is consistent with the fact that raising to the \(p\)-th power increases precision):
sage: z = x.nth_root(5); z 1 + 5^2 + 3*5^3 + 2*5^4 + 5^5 + 3*5^7 + 2*5^8 + O(5^9) sage: z^5 1 + 5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^10)
>>> from sage.all import * >>> z = x.nth_root(Integer(5)); z 1 + 5^2 + 3*5^3 + 2*5^4 + 5^5 + 3*5^7 + 2*5^8 + O(5^9) >>> z**Integer(5) 1 + 5^3 + 3*5^4 + 4*5^5 + 3*5^6 + O(5^10)
Everything works over extensions as well:
sage: # needs sage.libs.ntl sage: W.<a> = Zq(5^3) sage: S.<x> = W[] sage: R.<pi> = W.extension(x^7 - 5) sage: R(5).nth_root(7) pi + O(pi^141) sage: R(5).nth_root(7, all=True) [pi + O(pi^141)]
>>> from sage.all import * >>> # needs sage.libs.ntl >>> W = Zq(Integer(5)**Integer(3), names=('a',)); (a,) = W._first_ngens(1) >>> S = W['x']; (x,) = S._first_ngens(1) >>> R = W.extension(x**Integer(7) - Integer(5), names=('pi',)); (pi,) = R._first_ngens(1) >>> R(Integer(5)).nth_root(Integer(7)) pi + O(pi^141) >>> R(Integer(5)).nth_root(Integer(7), all=True) [pi + O(pi^141)]
An error is raised if the given element is not an \(n\)-th power in the ring:
sage: R(5).nth_root(11) # needs sage.libs.ntl Traceback (most recent call last): ... ValueError: this element is not a nth power
>>> from sage.all import * >>> R(Integer(5)).nth_root(Integer(11)) # needs sage.libs.ntl Traceback (most recent call last): ... ValueError: this element is not a nth power
Similarly, when precision on the input is too small, an error is raised:
sage: # needs sage.libs.ntl sage: x = R(1,6); x 1 + O(pi^6) sage: x.nth_root(5) Traceback (most recent call last): ... PrecisionError: not enough precision to be sure that this element is a nth power
>>> from sage.all import * >>> # needs sage.libs.ntl >>> x = R(Integer(1),Integer(6)); x 1 + O(pi^6) >>> x.nth_root(Integer(5)) Traceback (most recent call last): ... PrecisionError: not enough precision to be sure that this element is a nth power
Check that Issue #30314 is fixed:
sage: # needs sage.libs.ntl sage: K = Qp(29) sage: x = polygen(K) sage: L.<a> = K.extension(x^2 - 29) sage: L(4).nth_root(2) 2 + O(a^40)
>>> from sage.all import * >>> # needs sage.libs.ntl >>> K = Qp(Integer(29)) >>> x = polygen(K) >>> L = K.extension(x**Integer(2) - Integer(29), names=('a',)); (a,) = L._first_ngens(1) >>> L(Integer(4)).nth_root(Integer(2)) 2 + O(a^40)
- ordp(p=None)[source]#
Return the valuation of
self
, normalized so that the valuation of \(p\) is 1.INPUT:
self
– a \(p\)-adic elementp
– a prime (default:None
). If specified, will make sure thatp == self.parent().prime()
Note
The optional argument \(p\) is used for consistency with the valuation methods on integers and rationals.
OUTPUT:
integer – the valuation of
self
, normalized so that the valuation of \(p\) is 1EXAMPLES:
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
>>> from sage.all import * >>> R = Zp(Integer(5),Integer(20),'capped-rel') >>> R(Integer(0)).ordp() +Infinity >>> R(Integer(1)).ordp() 0 >>> R(Integer(2)).ordp() 0 >>> R(Integer(5)).ordp() 1 >>> R(Integer(10)).ordp() 1 >>> R(Integer(25)).ordp() 2 >>> R(Integer(50)).ordp() 2 >>> R(Integer(1)/Integer(2)).ordp() 0
- polylog(n, p_branch=0)[source]#
Return \(Li_n(\mathrm{self})\), the \(n\)-th \(p\)-adic polylogarithm of this element.
INPUT:
n
– a non-negative integerp_branch
– an element in the base ring or its fraction field; the implementation will choose the branch of the logarithm which sends \(p\) top_branch
EXAMPLES:
The \(n\)-th polylogarithm of \(-1\) is \(0\) for even \(n\):
sage: Qp(13)(-1).polylog(6) == 0 # needs sage.rings.real_mpfr sage.symbolic True
>>> from sage.all import * >>> Qp(Integer(13))(-Integer(1)).polylog(Integer(6)) == Integer(0) # needs sage.rings.real_mpfr sage.symbolic True
We can check some identities, for example those mentioned in [DCW2016]:
sage: x = Qp(7, prec=30)(1/3) sage: (x^2).polylog(4) - 8*x.polylog(4) - 8*(-x).polylog(4) == 0 # needs sage.symbolic True
>>> from sage.all import * >>> x = Qp(Integer(7), prec=Integer(30))(Integer(1)/Integer(3)) >>> (x**Integer(2)).polylog(Integer(4)) - Integer(8)*x.polylog(Integer(4)) - Integer(8)*(-x).polylog(Integer(4)) == Integer(0) # needs sage.symbolic True
sage: x = Qp(5, prec=30)(4) sage: x.polylog(2) + (1/x).polylog(2) + x.log(0)**2/2 == 0 # needs sage.symbolic True
>>> from sage.all import * >>> x = Qp(Integer(5), prec=Integer(30))(Integer(4)) >>> x.polylog(Integer(2)) + (Integer(1)/x).polylog(Integer(2)) + x.log(Integer(0))**Integer(2)/Integer(2) == Integer(0) # needs sage.symbolic True
sage: x = Qp(11, prec=30)(2) sage: x.polylog(2) + (1-x).polylog(2) + x.log(0)**2*(1-x).log(0) == 0 # needs sage.symbolic True
>>> from sage.all import * >>> x = Qp(Integer(11), prec=Integer(30))(Integer(2)) >>> x.polylog(Integer(2)) + (Integer(1)-x).polylog(Integer(2)) + x.log(Integer(0))**Integer(2)*(Integer(1)-x).log(Integer(0)) == Integer(0) # needs sage.symbolic True
\(Li_1(z) = -\log(1-z)\) for \(|z| < 1\):
sage: Qp(5)(10).polylog(1) == -Qp(5)(1-10).log(0) True
>>> from sage.all import * >>> Qp(Integer(5))(Integer(10)).polylog(Integer(1)) == -Qp(Integer(5))(Integer(1)-Integer(10)).log(Integer(0)) True
The dilogarithm of 1 is zero:
sage: Qp(5)(1).polylog(2) # needs sage.rings.real_mpfr sage.symbolic O(5^20)
>>> from sage.all import * >>> Qp(Integer(5))(Integer(1)).polylog(Integer(2)) # needs sage.rings.real_mpfr sage.symbolic O(5^20)
The cubing relation holds for the trilogarithm at 1:
sage: K = Qp(7) sage: z = K.zeta(3) sage: -8*K(1).polylog(3) == 9*(K(z).polylog(3) + K(z^2).polylog(3)) # needs sage.rings.padics sage.rings.real_mpfr sage.symbolic True
>>> from sage.all import * >>> K = Qp(Integer(7)) >>> z = K.zeta(Integer(3)) >>> -Integer(8)*K(Integer(1)).polylog(Integer(3)) == Integer(9)*(K(z).polylog(Integer(3)) + K(z**Integer(2)).polylog(Integer(3))) # needs sage.rings.padics sage.rings.real_mpfr sage.symbolic True
The polylogarithm of 0 is 0:
sage: Qp(11)(0).polylog(7) 0
>>> from sage.all import * >>> Qp(Integer(11))(Integer(0)).polylog(Integer(7)) 0
Only polylogarithms for positive \(n\) are defined:
sage: Qp(11)(2).polylog(-1) Traceback (most recent call last): ... ValueError: polylogarithm only implemented for n at least 0
>>> from sage.all import * >>> Qp(Integer(11))(Integer(2)).polylog(-Integer(1)) Traceback (most recent call last): ... ValueError: polylogarithm only implemented for n at least 0
Check that Issue #29222 is fixed:
sage: K = Qp(7) sage: print(K(1 + 7^11).polylog(4)) # needs sage.symbolic 6*7^14 + 3*7^15 + 7^16 + 7^17 + O(7^18)
>>> from sage.all import * >>> K = Qp(Integer(7)) >>> print(K(Integer(1) + Integer(7)**Integer(11)).polylog(Integer(4))) # needs sage.symbolic 6*7^14 + 3*7^15 + 7^16 + 7^17 + O(7^18)
ALGORITHM:
The algorithm of Besser-de Jeu, as described in [BdJ2008] is used.
AUTHORS:
Jennifer Balakrishnan - Initial implementation
Alex J. Best (2017-07-21) - Extended to other residue disks
Todo
Implement for extensions.
Use the change method to create K from
self.parent()
.
- rational_reconstruction()[source]#
Returns a rational approximation to this \(p\)-adic number.
This will raise an
ArithmeticError
if there are no valid approximations to the unit part with numerator and denominator bounded bysqrt(p^absprec / 2)
.See also
_rational_()
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()
>>> from sage.all import * >>> R = Zp(Integer(5),Integer(20),'capped-rel') >>> for i in range(Integer(11)): ... for j in range(Integer(1),Integer(10)): ... if j == Integer(5): ... continue ... assert i/j == R(i/j).rational_reconstruction()
- square_root(extend=True, all=False, algorithm=None)[source]#
Return the square root of this \(p\)-adic number.
INPUT:
self
– a \(p\)-adic element.extend
– a boolean (default:True
); ifTrue
, return a square root in an extension if necessary; ifFalse
and no root exists in the given ring or field, raise aValueError
.all
– a boolean (default:False
); ifTrue
, return a list of all square roots.algorithm
–"pari"
,"sage"
orNone
(default:None
); Sage provides an implementation for any extension of \(\QQ_p\), whereas only square roots over \(\QQ_p\) are implemented in PARI; the default is"pari"
if the ground field is \(\QQ_p\),"sage"
otherwise.
OUTPUT:
The square root or the list of all square roots of this \(p\)-adic number.
NOTE:
The square root is chosen (resp. the square roots are ordered) in a deterministic way.
EXAMPLES:
sage: R = Zp(3, 20) sage: R(0).square_root() 0 sage: R(1).square_root() 1 + O(3^20) sage: R(2).square_root(extend=False) Traceback (most recent call last): ... ValueError: element is not a square sage: -R(4).square_root() 2 + O(3^20) sage: R(9).square_root() 3 + O(3^21)
>>> from sage.all import * >>> R = Zp(Integer(3), Integer(20)) >>> R(Integer(0)).square_root() 0 >>> R(Integer(1)).square_root() 1 + O(3^20) >>> R(Integer(2)).square_root(extend=False) Traceback (most recent call last): ... ValueError: element is not a square >>> -R(Integer(4)).square_root() 2 + O(3^20) >>> R(Integer(9)).square_root() 3 + O(3^21)
When \(p = 2\), the precision of the square root is less than the input:
sage: R2 = Zp(2, 20) sage: R2(1).square_root() 1 + O(2^19) sage: R2(4).square_root() 2 + O(2^20) sage: R.<t> = Zq(2^10, 10) # needs sage.libs.ntl sage: u = 1 + 8*t # needs sage.libs.ntl sage: u.square_root() # needs sage.libs.ntl 1 + t*2^2 + t^2*2^3 + t^2*2^4 + (t^4 + t^3 + t^2)*2^5 + (t^4 + t^2)*2^6 + (t^5 + t^2)*2^7 + (t^6 + t^5 + t^4 + t^2)*2^8 + O(2^9) sage: # needs sage.libs.ntl sage: x = polygen(ZZ, 'x') sage: R.<a> = Zp(2).extension(x^3 - 2) sage: u = R(1 + a^4 + a^5 + a^7 + a^8, 10); u 1 + a^4 + a^5 + a^7 + a^8 + O(a^10) sage: v = u.square_root(); v 1 + a^2 + a^4 + a^6 + O(a^7)
>>> from sage.all import * >>> R2 = Zp(Integer(2), Integer(20)) >>> R2(Integer(1)).square_root() 1 + O(2^19) >>> R2(Integer(4)).square_root() 2 + O(2^20) >>> R = Zq(Integer(2)**Integer(10), Integer(10), names=('t',)); (t,) = R._first_ngens(1)# needs sage.libs.ntl >>> u = Integer(1) + Integer(8)*t # needs sage.libs.ntl >>> u.square_root() # needs sage.libs.ntl 1 + t*2^2 + t^2*2^3 + t^2*2^4 + (t^4 + t^3 + t^2)*2^5 + (t^4 + t^2)*2^6 + (t^5 + t^2)*2^7 + (t^6 + t^5 + t^4 + t^2)*2^8 + O(2^9) >>> # needs sage.libs.ntl >>> x = polygen(ZZ, 'x') >>> R = Zp(Integer(2)).extension(x**Integer(3) - Integer(2), names=('a',)); (a,) = R._first_ngens(1) >>> u = R(Integer(1) + a**Integer(4) + a**Integer(5) + a**Integer(7) + a**Integer(8), Integer(10)); u 1 + a^4 + a^5 + a^7 + a^8 + O(a^10) >>> v = u.square_root(); v 1 + a^2 + a^4 + a^6 + O(a^7)
However, observe that the precision increases to its original value when we recompute the square of the square root:
sage: v^2 # needs sage.libs.ntl 1 + a^4 + a^5 + a^7 + a^8 + O(a^10)
>>> from sage.all import * >>> v**Integer(2) # needs sage.libs.ntl 1 + a^4 + a^5 + a^7 + a^8 + O(a^10)
If the input does not have enough precision in order to determine if the given element has a square root in the ground field, an error is raised:
sage: # needs sage.libs.ntl sage: R(1, 6).square_root() Traceback (most recent call last): ... PrecisionError: not enough precision to be sure that this element has a square root sage: R(1, 7).square_root() 1 + O(a^4) sage: R(1+a^6, 7).square_root(extend=False) Traceback (most recent call last): ... ValueError: element is not a square
>>> from sage.all import * >>> # needs sage.libs.ntl >>> R(Integer(1), Integer(6)).square_root() Traceback (most recent call last): ... PrecisionError: not enough precision to be sure that this element has a square root >>> R(Integer(1), Integer(7)).square_root() 1 + O(a^4) >>> R(Integer(1)+a**Integer(6), Integer(7)).square_root(extend=False) Traceback (most recent call last): ... ValueError: element is not a square
In particular, an error is raised when we try to compute the square root of an inexact zero.
- str(mode=None)[source]#
Return a string representation of
self
.EXAMPLES:
sage: Zp(5,5,print_mode='bars')(1/3).str()[3:] '1|3|1|3|2'
>>> from sage.all import * >>> Zp(Integer(5),Integer(5),print_mode='bars')(Integer(1)/Integer(3)).str()[Integer(3):] '1|3|1|3|2'
- trace(base=None)[source]#
Returns the trace of this \(p\)-adic element over the base ring
INPUT:
base
– a subring of the parent (default: base ring)
OUTPUT:
The trace of this \(p\)-adic element over the given base.
EXAMPLES:
sage: Zp(5,5)(5).trace() # needs sage.libs.ntl 5 + O(5^6) sage: # needs sage.libs.ntl sage: K.<a> = QqCR(2^3,7) sage: S.<x> = K[] sage: L.<pi> = K.extension(x^4 - 4*a*x^3 + 2*a) sage: pi.trace() # trace over K # needs sage.symbolic a*2^2 + O(2^8) sage: (pi+1).trace() # needs sage.symbolic (a + 1)*2^2 + O(2^7)
>>> from sage.all import * >>> Zp(Integer(5),Integer(5))(Integer(5)).trace() # needs sage.libs.ntl 5 + O(5^6) >>> # needs sage.libs.ntl >>> K = QqCR(Integer(2)**Integer(3),Integer(7), names=('a',)); (a,) = K._first_ngens(1) >>> S = K['x']; (x,) = S._first_ngens(1) >>> L = K.extension(x**Integer(4) - Integer(4)*a*x**Integer(3) + Integer(2)*a, names=('pi',)); (pi,) = L._first_ngens(1) >>> pi.trace() # trace over K # needs sage.symbolic a*2^2 + O(2^8) >>> (pi+Integer(1)).trace() # needs sage.symbolic (a + 1)*2^2 + O(2^7)
- val_unit()[source]#
Return
(self.valuation(), self.unit_part())
. To be overridden in derived classes.EXAMPLES:
sage: Zp(5,5)(5).val_unit() (1, 1 + O(5^5))
>>> from sage.all import * >>> Zp(Integer(5),Integer(5))(Integer(5)).val_unit() (1, 1 + O(5^5))
- valuation(p=None)[source]#
Return the valuation of this element.
INPUT:
self
– a \(p\)-adic elementp
– a prime (default:None
). If specified, will make sure thatp == self.parent().prime()
Note
The optional argument \(p\) is used for consistency with the valuation methods on integers and rationals.
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
>>> from sage.all import * >>> R = Zp(Integer(17), Integer(4),'capped-rel') >>> a = R(Integer(2)*Integer(17)**Integer(2)) >>> a.valuation() 2 >>> R = Zp(Integer(5), Integer(4),'capped-rel') >>> R(Integer(0)).valuation() +Infinity
- xgcd(other)[source]#
Compute the extended gcd of this element and
other
.INPUT:
other
– an element in the same ring
OUTPUT:
A tuple
r
,s
,t
such thatr
is a greatest common divisor of this element andother
andr = s*self + t*other
.AUTHORS:
Julian Rueth (2012-10-19): initial version
Note
Since the elements are only given with finite precision, their greatest common divisor is in general not unique (not even up to units). For example \(O(3)\) is a representative for the elements 0 and 3 in the 3-adic ring \(\ZZ_3\). The greatest common divisor of \(O(3)\) and \(O(3)\) could be (among others) 3 or 0 which have different valuation. The algorithm implemented here, will return an element of minimal valuation among the possible greatest common divisors.
EXAMPLES:
The greatest common divisor is either zero or a power of the uniformizing parameter:
sage: R = Zp(3) sage: R.zero().xgcd(R.zero()) (0, 1 + O(3^20), 0) sage: R(3).xgcd(9) (3 + O(3^21), 1 + O(3^20), 0)
>>> from sage.all import * >>> R = Zp(Integer(3)) >>> R.zero().xgcd(R.zero()) (0, 1 + O(3^20), 0) >>> R(Integer(3)).xgcd(Integer(9)) (3 + O(3^21), 1 + O(3^20), 0)
Unlike for
gcd()
, the result is not lifted to the maximal precision possible in the ring; it is such thatr = s*self + t*other
holds true:sage: a = R(3,2); a 3 + O(3^2) sage: b = R(9,3); b 3^2 + O(3^3) sage: a.xgcd(b) (3 + O(3^2), 1 + O(3), 0) sage: a.xgcd(0) (3 + O(3^2), 1 + O(3), 0)
>>> from sage.all import * >>> a = R(Integer(3),Integer(2)); a 3 + O(3^2) >>> b = R(Integer(9),Integer(3)); b 3^2 + O(3^3) >>> a.xgcd(b) (3 + O(3^2), 1 + O(3), 0) >>> a.xgcd(Integer(0)) (3 + O(3^2), 1 + O(3), 0)
If both elements are zero, then the result is zero with the precision set to the smallest of their precisions:
sage: a = R.zero(); a 0 sage: b = R(0,2); b O(3^2) sage: a.xgcd(b) (O(3^2), 0, 1 + O(3^20))
>>> from sage.all import * >>> a = R.zero(); a 0 >>> b = R(Integer(0),Integer(2)); b O(3^2) >>> a.xgcd(b) (O(3^2), 0, 1 + O(3^20))
If only one element is zero, then the result depends on its precision:
sage: # needs sage.rings.padics sage: R(9).xgcd(R(0,1)) (O(3), 0, 1 + O(3^20)) sage: R(9).xgcd(R(0,2)) (O(3^2), 0, 1 + O(3^20)) sage: R(9).xgcd(R(0,3)) (3^2 + O(3^22), 1 + O(3^20), 0) sage: R(9).xgcd(R(0,4)) (3^2 + O(3^22), 1 + O(3^20), 0)
>>> from sage.all import * >>> # needs sage.rings.padics >>> R(Integer(9)).xgcd(R(Integer(0),Integer(1))) (O(3), 0, 1 + O(3^20)) >>> R(Integer(9)).xgcd(R(Integer(0),Integer(2))) (O(3^2), 0, 1 + O(3^20)) >>> R(Integer(9)).xgcd(R(Integer(0),Integer(3))) (3^2 + O(3^22), 1 + O(3^20), 0) >>> R(Integer(9)).xgcd(R(Integer(0),Integer(4))) (3^2 + O(3^22), 1 + O(3^20), 0)
Over a field, the greatest common divisor is either zero (possibly with finite precision) or one:
sage: K = Qp(3) sage: K(3).xgcd(0) (1 + O(3^20), 3^-1 + O(3^19), 0) sage: K.zero().xgcd(0) (0, 1 + O(3^20), 0) sage: K.zero().xgcd(K(0,2)) (O(3^2), 0, 1 + O(3^20)) sage: K(3).xgcd(4) (1 + O(3^20), 3^-1 + O(3^19), 0)
>>> from sage.all import * >>> K = Qp(Integer(3)) >>> K(Integer(3)).xgcd(Integer(0)) (1 + O(3^20), 3^-1 + O(3^19), 0) >>> K.zero().xgcd(Integer(0)) (0, 1 + O(3^20), 0) >>> K.zero().xgcd(K(Integer(0),Integer(2))) (O(3^2), 0, 1 + O(3^20)) >>> K(Integer(3)).xgcd(Integer(4)) (1 + O(3^20), 3^-1 + O(3^19), 0)