FLINT3.7.0-dev

Exponentiation with a precomputed inverse

Synopsis#include <flint/ulong_extras.h>
ulong n_powmod2_preinv(ulong a, slong exp, ulong n, ulong ninv)source
ulong n_powmod2(ulong a, slong exp, ulong n)source

Returns aexp mod na^{\mathit{exp}} \bmod n for a<na < n. Negative exponents are allowed; an exception is thrown if aa is then not invertible.

ulong n_powmod2_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv)source
ulong n_powmod_ui_preinv(ulong a, ulong exp, ulong n, ulong ninv, ulong norm)source

Returns aexp mod na^{\mathit{exp}} \bmod n for an unsigned exponent and a<na < n. n_powmod_ui_preinv requires normalised nn, like n_mulmod_preinv.

ulong n_powmod2_fmpz_preinv(ulong a, const fmpz_t exp, ulong n, ulong ninv)source

Returns aexp mod na^{\mathit{exp}} \bmod n for a nonnegative multiprecision exponent and a<na < n.

These functions compute ae mod na^e \bmod n for a reduced base a<na < n and a word-size modulus nn, using the ulong inverse from n_preinvert_limb (n_powmod2 computes it itself). They differ in the type of the exponent: slong for n_powmod2_preinv and n_powmod2, where a negative ee computes a power of a−1 mod na^{-1} \bmod n; ulong for the full unsigned range; and fmpz_t for nonnegative exponents of any size. The functions with a double inverse (n_powmod_precomp and its relatives) are documented separately.

By convention a0=1a^0 = 1 (also for a=0a = 0), reduced modulo nn, so the result is 0 when n=1n = 1.

Normalised moduli#

n_powmod_ui_preinv works like n_mulmod_preinv: the modulus is shifted left until its top bit is set, and the base is shifted by the same number of bits ss. For any nn, n_powmod_ui_preinv(a << s, e, n << s, ninv, s) >> s equals n_powmod2_ui_preinv(a, e, n, ninv), where ss is the number of leading zero bits of nn; n_powmod2_preinv is implemented this way. Calling it directly saves the shifts when the operands are already kept in shifted form.

Algorithm#

Right-to-left binary exponentiation: the base is squared once for each bit of the exponent below the top bit, and multiplied into the result once for each set bit after the lowest. Each step is one modular multiplication with a Möller–Granlund reduction, so the cost is at most 2log⁡2e2 \log_2 e modular multiplications.

Example#

Examplepowmod_basic.cchecked by make checkdoc
#include <flint/flint.h>
#include <flint/ulong_extras.h>

int main(void)
{
    ulong n = 1000003, ninv = n_preinvert_limb(n);
    ulong x, norm;

    /* Fermat: 2^(n-1) = 1 mod n for prime n */
    flint_printf("2^(n-1) mod n = %wu\n", n_powmod2_preinv(2, n - 1, n, ninv));

    /* a negative exponent gives a modular inverse */
    x = n_powmod2_preinv(3, -1, n, ninv);
    flint_printf("3^-1 mod n = %wu, check: %wu\n", x, n_mulmod2_preinv(3, x, n, ninv));

    /* n_powmod_ui_preinv works with the shifted (normalised) modulus */
    norm = flint_clz(n);
    x = n_powmod_ui_preinv(UWORD(5) << norm, 1000, n << norm, ninv, norm) >> norm;
    flint_printf("5^1000 mod n = %wu = %wu\n", x, n_powmod2_ui_preinv(5, 1000, n, ninv));
    return 0;
}
Output
2^(n-1) mod n = 1
3^-1 mod n = 666669, check: 1
5^1000 mod n = 463979 = 463979
Cite this page

The FLINT team, “Exponentiation with a precomputed inverse (ulong_extras.h),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/ulong_extras/powmod.html (generated 2026-11-02).