ulong_extras.h
#include <flint/ulong_extras.h>This module works with ulong, an unsigned integer of FLINT_BITS bits (64 on all common platforms). It provides division and modular arithmetic with precomputed inverses, primality testing, factoring, integer roots and elementary number-theoretic functions. Most higher-level modules (nmod, fmpz, the polynomial and matrix modules) rely on it.
For background, Choosing a method for modular arithmetic compares the ways of computing modulo a word-size integer, and Primality testing for word-size integers and Factoring word-size integers describe the algorithms behind n_is_prime and n_factor.
Conventions#
Throughout, .
- Functions ending in
_preinvtake a precomputed inverse of typeulongcomputed byn_preinvert_limb. Functions ending in_precomptake adoubleinverse computed byn_precompute_inverse. - A
2in the name (n_mod2_preinv,n_mulmod2_preinv) marks the variant with no size restrictions on its inputs. Variants without it are faster but may require reduced operands, a normalised modulus or a modulus below . n_ll_andn_lll_functions take operands of two or three limbs.- Precomputed inverses are assumed to match the modulus, and operands of modular functions are assumed to be reduced. None of this is checked.
Basic arithmetic#
int n_add_checked(ulong * a, ulong b, ulong c)int n_sub_checked(ulong * a, ulong b, ulong c)int n_mul_checked(ulong * a, ulong b, ulong c)Sets *a to , or modulo and returns 1 if the exact result does not fit in a ulong, otherwise 0.
Returns and respectively. Requires and .
ulong n_clog_2exp(ulong n, ulong b)Returns . Requires .
Returns with its lowest bits in reverse order; for example the 6-bit number becomes .
int n_sizeinbase(ulong n, int base)Returns the number of digits of in the given base (); n_sizeinbase returns 1 for . n_nonzero_sizeinbase10 is a branch-free version for base 10 and requires .
Integer roots and perfect powers#
int n_is_square(ulong x)Returns 1 if is a perfect square, otherwise 0.
MoreReturns for , or 0 if or is 0. n_rootrem also sets the remainder .
double n_cbrt_estimate(double a)int n_is_perfect_power235(ulong n)ulong n_factor_power235(ulong * exp, ulong n)n_is_perfect_power235 returns whether is a square, cube or fifth power. n_factor_power235 returns the root and sets *exp to if , and otherwise returns 0.
int n_is_perfect_power(ulong * root, ulong n)If with , returns and sets *root to ; otherwise returns 0. Both 0 and 1 count as squares. The found is not necessarily the largest possible.
Division and remainder#
These functions compute (and possibly the quotient) from a precomputed approximation of , which is much faster than a hardware division when the same is used repeatedly. The approximation is either a ulong (_preinv functions), a double (_precomp functions) or the data for Barrett or Lemire reduction. For a comparison of the methods see Choosing a method for modular arithmetic.
With a ulong inverse#
Returns the precomputed inverse of used by all _preinv functions [GraMol2010]. n_preinvert_limb_prenorm is a faster version for normalised (top bit set).
ulong n_mod2_preinv(ulong a, ulong n, ulong ninv)Returns . No restrictions on ; .
Full documentationReturns and sets *q to . The last two variants take the number of leading zero bits of as norm; n_divrem_preinv_unnorm requires .
ulong n_div2_preinv(ulong a, ulong n, ulong ninv)Returns the quotient . No restrictions on ; .
Full documentationReturns for the two-limb integer . No restrictions on ; .
Full documentationReturns for the three-limb integer . Requires .
Full documentationulong n_divrem_norm(ulong * q, ulong a, ulong n)Returns and sets *q to the quotient (0 or 1), assuming is normalised. No inverse is needed: the quotient is a single comparison.
With a double inverse#
double n_precompute_inverse(ulong n)Returns as a double, the precomputed inverse used by all _precomp functions. Requires .
ulong n_mod_precomp(ulong a, ulong n, double ninv)Returns . Requires , and .
Moreulong n_mod2_precomp(ulong a, ulong n, double ninv)Returns with no restrictions on or .
Moreulong n_divrem2_precomp(ulong * q, ulong a, ulong n, double npre)Returns and sets *q to the quotient. No restrictions on or .
Barrett and Lemire reduction#
Returns the precomputed inverse for n_mod_barrett. Requires .
ulong n_mod_barrett(ulong x, ulong n, ulong npre)ulong n_mod_barrett_lazy(ulong x, ulong n, ulong npre)Returns the precomputed inverse for n_mod_lemire. Requires .
ulong n_mod_lemire(ulong x, ulong n, ulong npre)Returns using the method of Lemire, Kaser and Kurz [LKK2019]. Only correct for .
Divisibility#
Returns 1 and sets *q to if divides ; otherwise returns 0 and sets *q to 0.
int n_divisible_odd_gm(ulong n, ulong inv1, ulong inv2)Returns whether the odd number divides , given and . Costs one multiplication. See Divisibility testing by multiplication.
int n_remove2_precomp(ulong * n, ulong p, double ppre)Divides *n by the largest possible power of and returns the exponent. Requires . n_remove2_precomp takes ppre = n_precompute_inverse(p).
Greatest common divisor#
Returns and sets *a, *b to unsigned values with . Requires .
Modular addition and inversion#
Returns , and for reduced operands.
Returns and sets *a to the with . Requires . When , returns 1 and sets *a to 0.
Returns the inverse of odd modulo ; the result is meaningless for even .
MoreModular multiplication#
Returns . No restrictions on , or .
Full documentationReturns , computing the inverse of on the fly. Use n_mulmod2_preinv when is reused.
Returns for normalised and reduced . If , and are the operands and modulus shifted left by norm bits, this is their product modulo the unshifted modulus, shifted left by norm bits.
Multiplication by a fixed operand#
These functions speed up computing for fixed and and many , as in scalar multiplication of vectors and matrices [Sho2021; Har2014]. They require .
Returns , the precomputed data for n_mulmod_shoup. Requires .
Returns given a_precomp from n_mulmod_precomp_shoup. Requires ; is arbitrary.
void n_mulmod_precomp_shoup_quo_rem(ulong * a_pr_quo, ulong * a_pr_rem, ulong a, ulong n)ulong n_mulmod_precomp_shoup_rem_from_quo(ulong a_pr_quo, ulong n)Compute both the quotient and the remainder , as needed by n_mulmod_and_precomp_shoup. The second function recovers the remainder from a known quotient.
void n_mulmod_and_precomp_shoup(ulong * ab, ulong * ab_precomp, ulong a, ulong b, ulong a_pr_quo, ulong a_pr_rem, ulong b_precomp, ulong n)Sets *ab to and *ab_precomp to its precomputed data , without a division. Requires . Useful for building tables of powers together with their precomputed data.
Modular exponentiation#
Returns for . Negative exponents are allowed; an exception is thrown if is then not invertible.
Full documentationReturns for an unsigned exponent and . n_powmod_ui_preinv requires normalised , like n_mulmod_preinv.
Returns for a nonnegative multiprecision exponent and .
Full documentationulong n_powmod_precomp(ulong a, slong exp, ulong n, double npre)ulong n_powmod_ui_precomp(ulong a, ulong exp, ulong n, double npre)Returns using a double inverse. Require and .
Chinese remaindering#
Returns the unique with and . Requires coprime with fitting in a ulong, and reduced . Nothing is checked.
Jacobi symbols#
int n_jacobi_unsigned(ulong x, ulong y)Returns the Jacobi symbol for odd (not checked), with a binary algorithm [ShaSor1993]. n_jacobi_unsigned accepts a full-limb .
Primes#
Finding, counting and enumerating primes. To run through consecutive primes, use a prime iterator (n_primes_t); the first primes and their inverses are also available from a per-thread cache.
ulong n_nextprime(ulong n, int proved)Returns the smallest prime greater than . Throws an exception if it does not fit in a ulong. The flag proved has no effect: the result is always a proved prime.
ulong n_prime_pi(ulong n)void n_prime_pi_bounds(ulong * lo, ulong * hi, ulong n)Return the number of primes , or set .
Morevoid n_nth_prime_bounds(ulong * lo, ulong * hi, ulong n)Return the -th prime (with ; throws an exception), or set .
Morevoid n_primes_init(n_primes_t iter)void n_primes_clear(n_primes_t iter)Initialise and clear a prime iterator.
ulong n_primes_next(n_primes_t iter)Returns the next prime and advances the iterator. The first call returns 2.
Morevoid n_primes_jump_after(n_primes_t iter, ulong n)Makes the iterator continue with the first prime greater than .
void n_compute_primes(ulong num_primes)const ulong * n_primes_arr_readonly(ulong num_primes)const double * n_prime_inverses_arr_readonly(ulong n)void n_cleanup_primes(void)Maintain a per-thread cache of the first primes and their double inverses. The _readonly functions return pointers into the cache, which stay valid until n_cleanup_primes is called in the same thread.
void n_primes_extend_small(n_primes_t iter, ulong bound)void n_primes_sieve_range(n_primes_t iter, ulong a, ulong b)Internal helpers of the prime iterator: extend its table of small primes until the second-largest entry is at least bound, or sieve the odd numbers in and point the iterator at the start of that block.
Primality testing#
n_is_prime, and n_ll_is_prime for two-limb integers, are the functions to use. The others are individual probable prime tests and two alternative primality proofs, of interest mainly for testing and experiments.
n_is_prime proves primality of any 64-bit integer with at most two strong probable prime tests, using table lookups, vectorised trial division and a hashed table of witnesses.
int n_is_prime(ulong n)Returns 1 if is prime and 0 otherwise. Deterministic for all .
Full documentationint n_is_prime_odd_no_trial(ulong n)Like n_is_prime for odd , but skips trial division. Faster when is already known to have no small factors.
int n_ll_is_prime(ulong nhi, ulong nlo)Primality test for the two-limb integer with . Returns 1 (prime), 0 (composite) or (unknown). The answer is always definite below about on 64-bit machines.
Moreint n_is_strong_probabprime2_preinv(ulong n, ulong ninv, ulong a, ulong d)int n_is_strong_probabprime_precomp(ulong n, double npre, ulong a, ulong d)Test whether odd is a strong probable prime to base [Mil1976; Rab1980], given the odd part of and . The _precomp version requires . See Strong probable prime test.
int n_is_probabprime_fermat(ulong n, ulong i)Returns whether . Requires and .
int n_is_probabprime_fibonacci(ulong n)Fibonacci probable prime test: checks , where is a Jacobi symbol [CraPom2005]. Requires .
int n_is_probabprime_lucas(ulong n)Lucas probable prime test, similar to the one of Baillie and Wagstaff [BaiWag1980].
int n_is_probabprime_BPSW(ulong n)Baillie–PSW probable prime test [PSW1980; BaiWag1980]. No composite passing it is known, and it has been checked against tables of pseudoprimes up to , so it is a primality test for word-size .
Moreint n_is_prime_pocklington(ulong n, ulong iterations)int n_is_prime_pseudosquare(ulong n)Primality test based on pseudosquares, following Theorem 2.7 of [LukPatWil1996].
Moreint n_is_probabprime(ulong n)Obsolete; calls n_is_prime.
Factoring#
OverviewFactoring word-size integersHown_factor combines trial division, primality testing, perfect power detection, Pollard–Brent rho, Hart's one-line method and SQUFOF to factor any 64-bit integer.
A factorisation into distinct primes, with fields num (the number of distinct primes), p[] (the primes) and exp[] (the exponents).
void n_factor_init(n_factor_t * factors)Initialises factors to the empty factorisation.
void n_factor(n_factor_t * factors, ulong n, int proved)Sets factors to the complete factorisation of (empty for ); factors need not be initialised. The flag proved has no effect, as all primality tests used are deterministic for word-size integers.
ulong n_factor_evaluate(const n_factor_t * factors)Returns , or 0 if it does not fit in a ulong.
void n_factor_insert(n_factor_t * factors, ulong p, ulong exp)Multiplies the factorisation by , adding to the exponent of if it is already present.
ulong n_factor_trial(n_factor_t * factors, ulong n, ulong num_primes)ulong n_factor_trial_range(n_factor_t * factors, ulong n, ulong start, ulong num_primes)Trial division by the first num_primes primes (starting at the prime with index start). Factors found are added to factors, which must be initialised; the unfactored cofactor is returned.
ulong n_factor_trial_partial(n_factor_t * factors, ulong n, ulong * prod, ulong num_primes, ulong limit)ulong n_factor_partial(n_factor_t * factors, ulong n, ulong limit, int proved)Partial factorisation: like n_factor_trial and n_factor, but stop as soon as the product of the prime factors found exceeds limit. Return the cofactor; n_factor_trial_partial also sets *prod to the product of the factors found.
ulong n_factor_one_line(ulong n, ulong iters)Hart's one-line factoring algorithm [Har2012], a variant of Fermat's method. Returns a factor of or 0. Faster than SQUFOF below about .
ulong n_factor_SQUFOF(ulong n, ulong iters)ulong n_ll_factor_SQUFOF(ulong nhi, ulong nlo, ulong iters)Shanks' square form factorisation as described by Gower and Wagstaff [GowWag2008]. Returns a factor of that fits in one limb, or 0 if none was found within iters iterations. The ll version takes a two-limb .
ulong n_factor_pp1(ulong n, ulong B1, ulong c)int n_factor_pollard_brent(ulong * factor, flint_rand_t state, ulong n_in, ulong max_tries, ulong max_iters)Pollard–Brent rho for an odd two-limb with . Returns 1 and writes a nontrivial two-limb factor on success, otherwise 0.
Moreint n_ll_factor_ecm(nn_ptr factor, ulong nhi, ulong nlo, ulong curves, ulong B1, ulong B2, flint_rand_t state)The elliptic curve method for an odd two-limb with , trying up to curves curves with bounds , (if , then is used). Returns 1 and writes a factor on success, otherwise 0.
int n_factor_ecm(ulong * f, ulong curves, ulong B1, ulong B2, flint_rand_t state, ulong n)Arithmetic functions#
int n_moebius_mu(ulong n)void n_moebius_mu_vec(int * mu, ulong len)Compute the Möbius function , with , or the values .
Moreint n_is_squarefree(ulong n)Returns whether is squarefree, that is, . By convention 1 is squarefree and 0 is not.
Returns Euler's totient , the number of coprime to .
Factorials#
ulong n_factorial_mod2_preinv(ulong n, ulong p, ulong pinv)ulong n_factorial_fast_mod2_preinv(ulong n, ulong p, ulong pinv)Square roots modulo n#
Returns the square root of modulo the prime that lies in , or 0 if is not a square. Requires .
Moreslong n_sqrtmod_2pow(ulong ** sqrt, ulong a, slong exp)slong n_sqrtmodn(ulong ** sqrt, ulong a, n_factor_t * fac)Compute all square roots of modulo , modulo , or modulo an integer given by its factorisation, and return their number. The roots are written to a newly allocated array stored in *sqrt, which the caller frees with flint_free. If is not a square, 0 is returned and *sqrt is set to NULL.
Primitive roots and discrete logarithms#
For odd non-square , returns some with Jacobi symbol ; for prime this is a quadratic nonresidue.
ulong n_primitive_root_prime_prefactor(ulong p, n_factor_t * factors)Return a primitive root modulo the prime . The prefactor version takes the prime factors of (exponents are ignored) and returns an with for every given.
ulong n_discrete_log_bsgs(ulong b, ulong a, ulong n)Returns with by baby-step giant-step [Sha1971], assuming is cyclic, that is, is 2, 4, or for an odd prime .
Random numbers#
All functions draw from a flint_rand_t state. Those with randtest in the name make corner cases such as 0, 1 and values with few set bits more likely, and are meant for test code.
ulong n_randlimb(flint_rand_t state)ulong _n_randlimb(flint_rand_t state)Returns a uniformly random limb. _n_randlimb is an inline version for tight loops.
ulong n_randbits(flint_rand_t state, unsigned int bits)Returns a uniformly random integer with exactly bits bits (the top bit is set), or 0 if bits is 0.
ulong n_randtest_bits(flint_rand_t state, int bits)Like n_randbits, but values with sparse binary representations are more likely.
ulong n_randint(flint_rand_t state, ulong limit)ulong n_urandint(flint_rand_t state, ulong limit)ulong _n_randint(flint_rand_t state, ulong limit)Returns a uniformly random integer in , or a random limb if limit is 0. The three functions are equivalent; _n_randint is inline.
ulong n_randtest(flint_rand_t state)Returns a random integer of random bit length between 0 and FLINT_BITS, with 0, 1, COEFF_MAX, WORD_MAX, UWORD_MAX and sparse values made more likely.
ulong n_randtest_not_zero(flint_rand_t state)Like n_randtest, but never returns 0.
ulong n_randprime(flint_rand_t state, ulong bits, int proved)Returns a random prime with exactly bits bits, where . The result is always a proved prime; the flag proved has no effect.
ulong n_randtest_prime(flint_rand_t state, int proved)Returns a random prime whose bit length is chosen at random between 2 and FLINT_BITS.
Double-limb modular exponentiation#
Low-level helpers for the base-2 and small-base strong probable prime tests in n_ll_is_prime. The modulus has two limbs () but must be below roughly .
void n_ll_small_preinv(nn_ptr minv, nn_srcptr m)Computes the two-limb inverse of a two-limb , as needed by n_ll_small_2_powmod and n_ll_small_powmod_triple.
void n_ll_small_2_powmod(nn_ptr res, nn_srcptr exp, nn_srcptr m, nn_srcptr minv)void n_ll_small_powmod_triple(nn_ptr res1, nn_ptr res2, nn_ptr res3, ulong b1, ulong b2, ulong b3, nn_srcptr exp, nn_srcptr m, nn_srcptr minv)Compute for small single-limb bases and two-limb and : the first function for , the second for three bases at once. Helpers for n_ll_is_prime.
ECM internals#
Building blocks of n_factor_ecm. Points are in Montgomery projective coordinates on curves in Montgomery form [Mon1987], and arithmetic is modulo using the parameters stored in n_ecm_inf.
Sets , using and .
void n_factor_ecm_add(ulong * x, ulong * z, ulong x1, ulong z1, ulong x2, ulong z2, ulong x0, ulong z0, ulong n, n_ecm_t n_ecm_inf)Sets given their difference .
void n_factor_ecm_mul_montgomery_ladder(ulong * x, ulong * z, ulong x0, ulong z0, ulong k, ulong n, n_ecm_t n_ecm_inf)Sets with the Montgomery ladder.
int n_factor_ecm_select_curve(ulong * f, ulong sigma, ulong n, n_ecm_t n_ecm_inf)Selects a curve and starting point from sigma with Suyama's parametrisation, storing , and in n_ecm_inf. Returns 1 if a factor of turned up along the way (stored in *f), otherwise 0.
References#
- [GraMol2010] N. Möller and T. Granlund, "Improved division by invariant integers", IEEE Transactions on Computers 60 (2011), 165–175, https://gmplib.org/~tege/division-paper.pdf
- [Bar1987] P. Barrett, "Implementing the Rivest Shamir and Adleman public key encryption algorithm on a standard digital signal processor", Advances in Cryptology – CRYPTO '86, LNCS 263 (1987), 311–323
- [LKK2019] D. Lemire, O. Kaser and N. Kurz, "Faster remainder by direct computation: applications to compilers and software libraries", Software: Practice and Experience 49 (2019), 953–970, https://arxiv.org/abs/1902.01961
- [Sho2021] V. Shoup, "Arithmetic software libraries", chapter 9 of Computational Cryptography, Cambridge University Press (2021), https://doi.org/10.1017/9781108854207.012
- [Har2014] D. Harvey, "Faster arithmetic for number-theoretic transforms", Journal of Symbolic Computation 60 (2014), 113–119, https://doi.org/10.1016/j.jsc.2013.09.002
- [ShaSor1993] J. Shallit and J. Sorenson, "A binary algorithm for the Jacobi symbol", ACM SIGSAM Bulletin 27 (1993), 4–11
- [Mil1976] G. L. Miller, "Riemann's hypothesis and tests for primality", Journal of Computer and System Sciences 13 (1976), 300–317
- [Rab1980] M. O. Rabin, "Probabilistic algorithm for testing primality", Journal of Number Theory 12 (1980), 128–138
- [CraPom2005] R. Crandall and C. Pomerance, Prime Numbers: A Computational Perspective, second edition, Springer (2005).
- [BaiWag1980] Robert Baillie; Samuel S. Wagstaff, Jr. (October 1980). "Lucas Pseudoprimes". Mathematics of Computation. 35 (152): 1391–1417.
- [PSW1980] C. Pomerance, J. L. Selfridge and S. S. Wagstaff, Jr., "The pseudoprimes to 25·10^9", Mathematics of Computation 35 (1980), 1003–1026
- [Poc1914] H. C. Pocklington, "The determination of the prime or composite nature of large numbers by Fermat's theorem", Proceedings of the Cambridge Philosophical Society 18 (1914), 29–30
- [BLS1975] J. Brillhart, D. H. Lehmer and J. L. Selfridge, "New primality criteria and factorizations of 2^m ± 1", Mathematics of Computation 29 (1975), 620–647
- [LukPatWil1996] R. F. Lukes and C. D. Patterson and H. C. Williams "Some results on pseudosquares" Math. Comp. 1996, no. 65, 361–372
- [Har2012] Hart, William B.. (2012) A one line factoring algorithm. Journal of the Australian Mathematical Society, Volume 92 (Number 1). pp. 61-69.
- [Leh1974] R. S. Lehman, "Factoring large integers", Mathematics of Computation 28 (1974), 637–646
- [GowWag2008] Jason Gower and Sam Wagstaff : "Square form factoring" Math. Comp. 77, 2008, pp 551-588, https://doi.org/10.1090/S0025-5718-07-02010-8
- [Wil1982] H. C. Williams, "A p+1 method of factoring", Mathematics of Computation 39 (1982), 225–234
- [Pol1975] J. M. Pollard, "A Monte Carlo method for factorization", BIT 15 (1975), 331–334
- [Bre1980] R. P. Brent, "An improved Monte Carlo factorization algorithm", BIT 20 (1980), 176–184
- [Len1987] H. W. Lenstra, Jr., "Factoring integers with elliptic curves", Annals of Mathematics 126 (1987), 649–673
- [ZD2006] P. Zimmermann and B. Dodson, "20 years of ECM", Algorithmic Number Theory (ANTS VII), LNCS 4076 (2006), 525–542
- [Pol1974] J. M. Pollard, "Theorems on factorization and primality testing", Proceedings of the Cambridge Philosophical Society 76 (1974), 521–528
- [BGS2007] A. Bostan, P. Gaudry and É. Schost, "Linear recurrences with polynomial coefficients and application to integer factorization and Cartier–Manin operator", SIAM Journal on Computing 36 (2007), 1777–1806
- [Sha1971] D. Shanks, "Class number, a theory of factorization, and genera", Proc. Symp. Pure Math. 20, American Mathematical Society (1971), 415–440
- [Mon1987] P. L. Montgomery, "Speeding the Pollard and elliptic curve methods of factorization", Mathematics of Computation 48 (1987), 243-264, https://doi.org/10.1090/S0025-5718-1987-0866113-7
The FLINT team, “ulong_extras.h (module overview),” FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev, 2026. https://flintlib.org/doc/ulong_extras/index.html (generated 2026-11-02).
@misc{flint-doc-ulong-extras-index,
author = {{The FLINT team}},
title = {{ulong\_extras.h (module overview)}},
howpublished = {FLINT: Fast Library for Number Theory, documentation, version 3.7.0-dev},
year = {2026},
url = {https://flintlib.org/doc/ulong_extras/index.html},
note = {Generated 2026-11-02}
}