FLINT3.7.0-dev
Module · 87 functions

padic.h

#include <flint/padic.h>

This module implements arithmetic in the field Qp\mathbf{Q}_p of pp-adic numbers, for a prime pp of any size. An element is a padic_t, which stores a value x=pvux = p^v u with u,v∈Zu, v \in \mathbb{Z} together with an absolute precision NN; the value represents the residue class of xx modulo pNp^N. The prime, a table of powers of pp and the printing mode live in a separate context padic_ctx_t that is passed to every function. Each function computes its result exactly from the values of its inputs and then reduces it modulo pNp^N for the precision NN of the output, much as MPFR rounds to the precision of the output variable; the precision of the inputs is not used, and no error bound is propagated.

The guide Precision in the padic module explains this model with an example. Polynomials and matrices over Qp\mathbf{Q}_p are in padic_poly.h and padic_mat.h, unramified extensions in qadic.h. The newer module padic_radix.h implements Qp\mathbf{Q}_p for word-size pp with tracked error bounds and the generic ring interface.

Overviewp-adic arithmetic in FLINTThe modules for p-adic numbers, their precision models and representations, and which algorithm each function uses for inversion, square roots, the exponential and logarithm, Teichmüller lifts, the Frobenius map, norms and traces.

Guides#

Representation#

A pp-adic number pvu+O(pN)p^v u + O(p^N). The structure has the fields u (an fmpz), v and N (both slong). A padic_t is an array of one padic_struct, so it is passed by reference.

The value is in canonical form if p∤up \nmid u, or if u=v=0u = v = 0. It is reduced if moreover 0<u<pN−v0 < u < p^{N - v} when u≠0u \ne 0, so that a reduced element with v≥Nv \ge N is zero. All functions require canonical inputs and produce reduced outputs, except where the description says otherwise. The precision NN belongs to the variable: it is set when the variable is initialised, may be changed through padic_prec, and is never changed by arithmetic (padic_swap swaps it along with the value). NN may be zero or negative.

AlgorithmPrecision and representation of p-adic numbersHow FLINT represents a p-adic number as p^v u modulo p^N, the difference between absolute and relative precision, how much precision each arithmetic operation preserves, and the two precision models used by padic/qadic and by padic_radix.
fmpz * padic_unit(const padic_t op)

Returns a pointer to the unit part uu, which can be passed to the functions of fmpz.h.

The valuation vv and the precision NN of x, as lvalues of type slong. Lowering the precision of a reduced element does not reduce it; call padic_reduce afterwards.

Return the valuation vv and the precision NN of op.

The precision given to a variable by padic_init, equal to 20.

Context#

A context for Qp\mathbf{Q}_p. The fields are p (an fmpz_t), pinv (a double approximation of 1/p1/p, used when pp fits in a word), the table pow with pow[i] =pmin+i= p^{\mathtt{min} + i} for 0≤i<max−min0 \le i < \mathtt{max} - \mathtt{min}, the bounds min and max, and mode, the printing mode, which may be changed at any time.

The printing modes PADIC_TERSE, PADIC_SERIES and PADIC_VAL_UNIT. For x=12⋅7−1∈Q7x = 12 \cdot 7^{-1} \in \mathbf{Q}_7 they print 12/7, 5*7^-1 + 1 and 12*7^-1: as a rational number, as the sum of its pp-adic digits, and as unit times power of pp.

void padic_ctx_init(padic_ctx_t ctx, const fmpz_t p, slong min, slong max, enum padic_print_mode mode)

Initialises ctx for the prime pp with precomputed powers pep^e for min≤e<max\mathtt{min} \le e < \mathtt{max} and the given printing mode. Throws unless 0≤min≤max0 \le \mathtt{min} \le \mathtt{max}. That pp is prime is not checked; for composite pp the behaviour is undefined.

More

Clears the context.

void padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx)

Sets rop to pep^e, copying it from the table when possible. Throws if ee exceeds WORD_MAX.

int _padic_ctx_pow_ui(fmpz_t rop, ulong e, const padic_ctx_t ctx)

Makes the uninitialised rop equal to pep^e. If pep^e is in the table, rop becomes a shallow copy of the table entry, which must be neither modified nor cleared, and the function returns 0. Otherwise it initialises rop, computes the power and returns 1, and the caller must clear rop. Throws if ee exceeds WORD_MAX.

Memory management#

Initialise rop to zero with precision PADIC_DEFAULT_PREC (that is, 20), respectively NN.

Clears rop.

Brings rop into canonical form by moving all factors pp of uu into vv, and sets v=0v = 0 if u=0u = 0. Does not reduce.

void _padic_reduce(padic_t rop, const padic_ctx_t ctx)

Reduces the canonical rop modulo pNp^N: replaces uu by u mod pN−vu \bmod p^{N - v} if v<Nv < N, and sets rop to zero otherwise.

void padic_reduce(padic_t rop, const padic_ctx_t ctx)

Canonicalises and reduces rop.

Random generation#

void padic_randtest(padic_t rop, flint_rand_t state, const padic_ctx_t ctx)

Sets rop to a random reduced element. Its valuation, when it is nonzero, lies in [−⌈N/10⌉,N)[-\lceil N/10 \rceil, N) for N>0N > 0, in [N−⌈−N/10⌉,N)[N - \lceil -N/10 \rceil, N) for N<0N < 0 and in [−10,0)[-10, 0) for N=0N = 0.

Like padic_randtest, but nonzero: after ten zero draws it sets rop to pN−1p^{N - 1}.

Sets rop to a random reduced pp-adic integer, with valuation in [0,N)[0, N), or to zero if N≤0N \le 0.

Assignment and conversion#

The functions that set a padic_t set it to the value of the input, reduced modulo pNp^N for the precision NN of the output.

void padic_set(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Sets rop to op. The precision of rop is kept.

void padic_set_si(padic_t rop, slong op, const padic_ctx_t ctx)
void padic_set_ui(padic_t rop, ulong op, const padic_ctx_t ctx)
void padic_set_fmpz(padic_t rop, const fmpz_t op, const padic_ctx_t ctx)

Set rop to the integer op.

void padic_set_fmpq(padic_t rop, const fmpq_t op, const padic_ctx_t ctx)

Sets rop to the canonical rational number op. The power of pp in the denominator becomes a negative valuation, and the rest of the denominator is inverted modulo pN−vp^{N - v}.

void padic_set_mpz(padic_t rop, const mpz_t op, const padic_ctx_t ctx)
void padic_set_mpq(padic_t rop, const mpq_t op, const padic_ctx_t ctx)

Set rop to the GMP integer or rational op. These are declared only if gmp.h is included before padic.h.

void padic_get_fmpz(fmpz_t rop, const padic_t op, const padic_ctx_t ctx)

Sets rop to the integer pvup^v u represented by op. Throws if v<0v < 0.

void padic_get_fmpq(fmpq_t rop, const padic_t op, const padic_ctx_t ctx)

Sets rop to the rational number pvup^v u represented by op.

void padic_get_mpz(mpz_t rop, const padic_t op, const padic_ctx_t ctx)
void padic_get_mpq(mpq_t rop, const padic_t op, const padic_ctx_t ctx)

GMP versions of padic_get_fmpz (which throws if v<0v < 0) and padic_get_fmpq. Declared only if gmp.h is included before padic.h.

void padic_swap(padic_t op1, padic_t op2)

Swaps op1 and op2, including their precisions. This differs from an exchange through padic_set when the precisions differ.

Sets rop to zero.

void padic_one(padic_t rop)

Sets rop to one, or to zero if its precision is not positive.

Comparison#

int padic_is_zero(const padic_t op)

Returns whether op is zero, that is, whether u=0u = 0.

int padic_is_one(const padic_t op)

Returns whether u=1u = 1 and v=0v = 0.

int padic_equal(const padic_t op1, const padic_t op2)

Returns whether the stored values are equal, that is, whether u1=u2u_1 = u_2 and v1=v2v_1 = v_2. The precisions are not compared: elements of different precisions that agree modulo the smaller power of pp are equal only if their stored values coincide.

Arithmetic#

All functions in this section allow aliasing between the output and the inputs.

void padic_add(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx)
void padic_sub(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx)

Set rop to op1+op2op_1 + op_2 and op1−op2op_1 - op_2, reduced.

void padic_neg(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Sets rop to −op-op, reduced.

void padic_mul(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx)

Sets rop to op1 op2op_1 \, op_2, reduced: the units are multiplied and the product is reduced modulo pN−v1−v2p^{N - v_1 - v_2}.

void padic_shift(padic_t rop, const padic_t op, slong v, const padic_ctx_t ctx)

Sets rop to op⋅pvop \cdot p^v, reduced. Here vv may be negative.

void padic_div(padic_t rop, const padic_t op1, const padic_t op2, const padic_ctx_t ctx)

Sets rop to op1/op2op_1 / op_2, reduced. Throws if op2op_2 is zero.

void padic_inv(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Sets rop to 1/op1/op, reduced. For op=pvuop = p^v u this is p−vp^{-v} times the inverse of uu modulo pN+vp^{N + v}, computed by Hensel lifting; if N+v≤0N + v \le 0 the result is zero. Throws if op is zero.

More
int padic_sqrt(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Returns whether op is a square in Qp\mathbf{Q}_p and in that case sets rop to a square root, reduced. If the return value is 0, the value of rop is undefined.

More
void padic_pow_si(padic_t rop, const padic_t op, slong e, const padic_ctx_t ctx)

Sets rop to opeop^e, reduced, for any integer ee, with op0=1op^0 = 1. For e<0e < 0 the unit is first inverted modulo pN−evp^{N - ev}. If op is zero and e≠0e \ne 0 the result is zero, also for e<0e < 0. Assumes that evev does not overflow a slong.

More

Exponential and logarithm#

Exponential and logarithm describes the functions of this section and the choice of algorithm in more detail.

Returns nn such that ord⁡p(xj/j!)≥N\operatorname{ord}_p(x^j / j!) \ge N for all j≥nj \ge n and all xx with ord⁡p(x)=v\operatorname{ord}_p(x) = v, so that the exponential series can be truncated after nn terms. Requires 1≤v<N1 \le v < N for odd pp and 2≤v<N2 \le v < N for p=2p = 2.

More
void _padic_exp(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N)
void _padic_exp_rectangular(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N)
void _padic_exp_balanced(fmpz_t rop, const fmpz_t u, slong v, const fmpz_t p, slong N)

Set rop to exp⁡(pvu)\exp(p^v u) reduced modulo pNp^N. Require pvu≠0p^v u \ne 0, v<Nv < N, and v≥1v \ge 1 for odd pp, v≥2v \ge 2 for p=2p = 2. Allow aliasing between rop and uu. _padic_exp uses the rectangular algorithm for N<1024N < 1024 and the balanced one otherwise.

int padic_exp(padic_t rop, const padic_t op, const padic_ctx_t ctx)
int padic_exp_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx)
int padic_exp_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Return whether the exponential series converges at op, that is, whether op is zero or has valuation at least 1 (odd pp) or 2 (p=2p = 2), and if so set rop to exp⁡(op)\exp(op), reduced. Otherwise rop is not changed. The rectangular version evaluates the series by rectangular splitting, the balanced version by the pp-adic analogue of the bit-burst method with binary splitting, which is quasi-linear in NN for fixed pp.

Full documentation

Returns bb such that iv−ord⁡p(i)≥Niv - \operatorname{ord}_p(i) \ge N for all i≥bi \ge b, so that the logarithm series for an argument of valuation vv can be truncated after b−1b - 1 terms. Requires 1≤v<N1 \le v < N and N<2FLINT_BITS−2N < 2^{\mathtt{FLINT\_BITS} - 2}; throws if NN is larger.

void _padic_log(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N)
void _padic_log_rectangular(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N)
void _padic_log_satoh(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N)
void _padic_log_balanced(fmpz_t z, const fmpz_t y, slong v, const fmpz_t p, slong N)

Set zz to

log⁡(1−y)=−∑i=1∞yii mod pN\log(1 - y) = -\sum_{i = 1}^{\infty} \frac{y^i}{i} \bmod p^N

for an integer y≠0y \ne 0 with v=ord⁡p(y)v = \operatorname{ord}_p(y) and 1≤v<N1 \le v < N; the logarithm of xx is obtained with y=1−xy = 1 - x. Do not allow aliasing between yy and zz. _padic_log uses the rectangular version for N<512/bN < 512 / b, where bb is the bit length of pp, and the balanced version otherwise. The balanced version does not use vv.

int padic_log(padic_t rop, const padic_t op, const padic_ctx_t ctx)
int padic_log_rectangular(padic_t rop, const padic_t op, const padic_ctx_t ctx)
int padic_log_satoh(padic_t rop, const padic_t op, const padic_ctx_t ctx)
int padic_log_balanced(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Return whether the logarithm series converges at op, that is, whether ord⁡p(op−1)≥1\operatorname{ord}_p(op - 1) \ge 1, and if so set rop to log⁡(op)\log(op), reduced. Otherwise rop is not changed. The condition is the same for every pp, including p=2p = 2. The rectangular version evaluates the series by rectangular splitting, the Satoh version first raises op to the power pkp^k with k=⌊N⌋k = \lfloor \sqrt N \rfloor, and the balanced version writes op as a product of factors whose logarithms are summed by binary splitting.

Full documentation

Teichmüller lifts and factorials#

void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N)

Sets rop to the Teichmüller lift of the pp-adic unit op modulo pNp^N: the unique root of unity of order dividing p−1p - 1 that is congruent to op modulo pp. Requires N≥1N \ge 1 and allows aliasing. For p=2p = 2 the result is 1.

void padic_teichmuller(padic_t rop, const padic_t op, const padic_ctx_t ctx)

Sets rop to the Teichmüller lift of op, reduced. If op is zero or divisible by pp the result is zero (which satisfies tp=tt^p = t but is not a root of unity). Throws if op has negative valuation.

More

Return ord⁡2(n!)\operatorname{ord}_2(n!) and ord⁡p(n!)\operatorname{ord}_p(n!), by Legendre's formula ∑k≥1⌊n/pk⌋\sum_{k \ge 1} \lfloor n / p^k \rfloor. The result fits in a ulong since ord⁡p(n!)≤(n−1)/(p−1)\operatorname{ord}_p(n!) \le (n - 1)/(p - 1). padic_val_fac_ui returns 0 if pp does not fit in a ulong.

void padic_val_fac(fmpz_t rop, const fmpz_t op, const fmpz_t p)

Sets rop to ord⁡p(op!)\operatorname{ord}_p(op!). Throws if op is negative.

Input and output#

char * _padic_get_str(char * str, const padic_t op, const fmpz_t p, enum padic_print_mode mode)
char * padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx)

Return the string representation of op in the given printing mode, respectively the mode of the context. If str is NULL, a new string is allocated with flint_malloc; otherwise str must be large enough and is returned.

int _padic_fprint(FILE * file, const fmpz_t u, slong v, const padic_ctx_t ctx)
int padic_fprint(FILE * file, const padic_t op, const padic_ctx_t ctx)
int _padic_print(const fmpz_t u, slong v, const padic_ctx_t ctx)
int padic_print(const padic_t op, const padic_ctx_t ctx)

Print pvup^v u, respectively op, to file or to stdout in the printing mode of the context, and return 1.

void padic_debug(const padic_t op)

Prints the raw fields of op to stdout in the form (u v N).

Low-level functions#

These functions work on integers rather than on padic_t. The lifting functions implement the Newton iteration of Hensel lifting of inverses, square roots and Teichmüller lifts, which runs through the precisions a0=Na_0 = N, ai+1=⌈ai/2⌉a_{i+1} = \lceil a_i / 2 \rceil down to 1 and back up.

Precomputed data for repeated inversion modulo pNp^N: the length n of the precision sequence and an array pow holding the powers paip^{a_i} together with scratch space.

Initialise S for inversion modulo pNp^N, N≥1N \ge 1, and clear it.

void _padic_inv_precomp(fmpz_t rop, const fmpz_t op, const padic_inv_t S)

Sets rop to the inverse of the pp-adic unit op modulo pNp^N, using the data S. The scratch space in S is overwritten, so S must not be shared between threads. Allows aliasing.

void _padic_inv(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N)

Sets rop to the inverse of the pp-adic unit op modulo pNp^N, for N≥1N \ge 1. The result is in [0,pN)[0, p^N). Allows aliasing.

int _padic_sqrt(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N)

Returns whether the pp-adic unit op is a square in Zp\mathbf{Z}_p and if so sets rop to a square root modulo pNp^N, for N≥1N \ge 1. For odd pp this is decided modulo pp, for p=2p = 2 modulo 8. Allows aliasing.

Returns the sequence a0=Na_0 = N, ai+1=⌈ai/2⌉a_{i+1} = \lceil a_i/2 \rceil, ending with an−1=1a_{n-1} = 1, and sets *n to its length ⌈log⁡2N⌉+1\lceil \log_2 N \rceil + 1. Requires N≥1N \ge 1. The array is allocated with flint_malloc and must be freed with flint_free.

void _padic_lifts_pows(fmpz * pow, const slong * a, slong n, const fmpz_t p)

Sets pow[i] to paip^{a_i} for a sequence aa of length nn as computed by _padic_lifts_exps, using about one multiplication per entry.

Cite this page

The FLINT team, “padic.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/padic/index.html (generated 2026-11-02).