|
Number Theory Utils 0.2.0
|
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
Functions for dealing with modular arithmetic on 64 bit integers (not suitable for large integers which may overflow, around 2^31. a bignum-enabled version may be created to handle this)
Definition in file modular_math.h.
Go to the source code of this file.
Data Structures | |
| struct | nut_u64_Pitcharr |
| A fixed capacity array. More... | |
Macros | |
| #define | NUT_ATTR_ACCESS(...) |
Wrapper for gcc's access function annotation - no clang equivalent, and currently disabled because it is bugged See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html. | |
| #define | NUT_ATTR_NO_SAN(name) |
| Prevent clang from reporting spurious errors when a length zero array is passed to a length annotated function parameter. | |
| #define | NUT_ATTR_CONST |
| Wrapper for gnu::const attr - such a function has no side effects and cannot read memory. | |
| #define | NUT_ATTR_PURE |
| Wrapper for gnu::pure attr - similar to const but the function can read non-volatile memory (including passed-in pointers) | |
| #define | NUT_ATTR_NODISCARD |
| Wrapper for nodiscard attr - requires return value be used. | |
| #define | NUT_ATTR_NONNULL(...) |
| Wrapper for gnu::nonnull attr. | |
| #define | NUT_ATTR_RETURNS_NONNULL |
| Wrapper for gnu::returns_nonnull attr. | |
| #define | NUT_ATTR_MALLOC |
| Wrapper for gnu::malloc attr - indicates the function returns a malloc'd pointer that must be free'd. | |
| #define | NUT_ATTR_ARTIFICIAL |
| Wrapper for gnu::artificial attr - hint that the function should be ignored in debuggers. | |
Typedefs | |
| typedef signed __int128 | int128_t |
| Pretty name for signed 128 bit integer. | |
| typedef unsigned __int128 | uint128_t |
| Pretty name for unsigned 128 bit integer. | |
Functions | |
| uint64_t | nut_u64_pow (uint64_t b, uint64_t e) |
| Compute nonnegative integral power of integer using binary exponentiation. | |
| uint128_t | nut_u128_pow (uint128_t b, uint64_t e) |
| Compute nonnegative integral power of integer using binary exponentiation. | |
| uint64_t | nut_u64_powmod (uint64_t b, uint64_t e, uint64_t n) |
| Compute nonnegative integral power of a number modulo another using binary exponentiation. | |
| uint64_t | nut_u64_binom (uint64_t n, uint64_t k) |
| Compute single binomial coefficient semi-naively. | |
| uint64_t | nut_u64_binom_next (uint64_t n, uint64_t k, uint64_t prev) |
| Compute the binomial coefficient for (n choose k) given the binomial coefficient for (n choose k-1) Simply uses the recurrence (n choose k) = (n - k + 1)/k * (n choose k-1) The starting point should be (n choose 0) = 1. | |
| uint64_t | nut_u64_prand (uint64_t a, uint64_t b) |
| Generate a (pseudo)random integer uniformly from [a, b). | |
| uint64_t | nut_u64_rand (uint64_t a, uint64_t b) |
| Generate a (strong) random integer uniformly from [a, b). | |
| int64_t | nut_i64_egcd (int64_t a, int64_t b, int64_t *restrict _t, int64_t *restrict _s) |
| Compute d = gcd(a, b) and x, y st. | |
| int64_t | nut_i64_modinv (int64_t a, int64_t b) |
Find the multiplicative inverse of a mod b If b is a power of 2, use nut_i64_modinv_2t Just a wrapper around nut_i64_egcd. | |
| uint64_t | nut_u64_modinv_2t (uint64_t a, uint64_t t) |
| Find the multiplicative inverse of a mod 2**t This uses a hensel/newton like iterative algorithm, described here https://crypto.stackexchange.com/a/47496 Basically, we use a lookup table to get the inverse mod 2**8, and then use the fact that ax = 1 mod 2**k --> ax(2-ax) = 1 mod 2**(2k) to lift the inverse to mod 2**16, mode 2**32, etc as needed. | |
| int64_t | nut_i64_mod (int64_t a, int64_t n) |
| Compute the Euclidean remainder r = a mod n for positive n so that 0 <= r < n. | |
| int64_t | nut_i64_crt (int64_t a, int64_t p, int64_t b, int64_t q) |
| Compute n mod pq st n = a mod p and n = b mod q, where p and q are coprime. | |
| int128_t | nut_i128_crt (int64_t a, int64_t p, int64_t b, int64_t q) |
| Compute n mod pq st n = a mod p and n = b mod q, where p and q are coprime. | |
| int64_t | nut_i64_lcm (int64_t a, int64_t b) |
| Compute the least common multiple of a and b Divides the product by the gcd so can overflow for large arguments. | |
| uint64_t | nut_u64_binom_next_mod_2t (uint64_t n, uint64_t k, uint64_t t, uint64_t *restrict v2, uint64_t *restrict p2) |
| Compute the binomial coefficient for (n choose k) given the binomial coefficient for (n choose k-1) Simply uses the recurrence (n choose k) = (n - k + 1)/k * (n choose k-1) The starting point should be (n choose 0) = 1. | |
| int64_t | nut_i64_jacobi (int64_t n, int64_t k) |
| Compute the Jacobi symbol of n mod k. | |
| uint64_t * | nut_u64_make_jacobi_tbl (uint64_t p, int64_t partial_sums[restrict static p]) |
| Compute the Jacobi symbol for all numbers mod a prime. | |
| int64_t | nut_u64_jacobi_tbl_get (uint64_t n, uint64_t p, const uint64_t is_qr[restrict static(p+63)/64]) |
Convenience function to get the jacobi symbol for n from a table The table should come from nut_u64_make_jacobi_tbl. | |
| int64_t | nut_i64_rand_nr_mod (int64_t p) |
| Compute a random number mod a prime that is not a quadratic residue. | |
| int64_t | nut_i64_sqrt_shanks (int64_t n, int64_t p) |
| Compute the square root of a quadratic residue mod a prime. | |
| int64_t | nut_i64_sqrt_cipolla (int64_t n, int64_t p) |
| Compute the square root of a quadratic residue mod a prime. | |
| int64_t | nut_i64_sqrt_mod (int64_t n, int64_t p) |
| Compute the square root of a quadratic residue mod a prime. | |
| uint64_t | nut_i32_fastmod_init (uint32_t pd) |
| Compute a constant to use to do modular division faster. | |
| uint64_t | nut_u32_fastmod_init (uint32_t d) |
| Compute a constant to use to do modular division faster. | |
| uint128_t | nut_i64_fastmod_init (uint64_t pd) |
| Compute a constant to use to do modular division faster. | |
| uint128_t | nut_u64_fastmod_init (uint64_t d) |
| Compute a constant to use to do modular division faster. | |
| int32_t | nut_i32_fastmod_trunc (int32_t n, uint32_t pd, uint64_t c) |
| Compute n mod d, choosing the smallest signed remainder. | |
| int32_t | nut_i32_fastmod_floor (int32_t n, uint32_t pd, uint64_t c) |
| Compute n mod d, choosing the euclidean remainder. | |
| uint32_t | nut_u32_fastmod (uint32_t n, uint32_t d, uint64_t c) |
| Compute n mod d faster using a precomputed constant. | |
| int64_t | nut_i64_fastmod_trunc (int64_t n, uint64_t pd, uint128_t c) |
| Compute n mod d, choosing the smallest signed remainder. | |
| int64_t | nut_i64_fastmod_floor (int64_t n, uint64_t pd, uint128_t c) |
| Compute n mod d, choosing the euclidean remainder. | |
| uint64_t | nut_u64_fastmod (uint64_t n, uint64_t d, uint128_t c) |
| Compute n mod d faster using a precomputed constant. | |
| #define NUT_ATTR_ACCESS | ( | ... | ) |
Wrapper for gcc's access function annotation - no clang equivalent, and currently disabled because it is bugged See https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html.
Definition at line 40 of file modular_math.h.
| #define NUT_ATTR_NO_SAN | ( | name | ) |
Prevent clang from reporting spurious errors when a length zero array is passed to a length annotated function parameter.
Definition at line 47 of file modular_math.h.
| #define NUT_ATTR_CONST |
Wrapper for gnu::const attr - such a function has no side effects and cannot read memory.
Definition at line 54 of file modular_math.h.
| #define NUT_ATTR_PURE |
Wrapper for gnu::pure attr - similar to const but the function can read non-volatile memory (including passed-in pointers)
Definition at line 61 of file modular_math.h.
| #define NUT_ATTR_NODISCARD |
Wrapper for nodiscard attr - requires return value be used.
Definition at line 68 of file modular_math.h.
| #define NUT_ATTR_NONNULL | ( | ... | ) |
Wrapper for gnu::nonnull attr.
Definition at line 75 of file modular_math.h.
| #define NUT_ATTR_RETURNS_NONNULL |
Wrapper for gnu::returns_nonnull attr.
Definition at line 82 of file modular_math.h.
| #define NUT_ATTR_MALLOC |
Wrapper for gnu::malloc attr - indicates the function returns a malloc'd pointer that must be free'd.
Definition at line 89 of file modular_math.h.
| #define NUT_ATTR_ARTIFICIAL |
Wrapper for gnu::artificial attr - hint that the function should be ignored in debuggers.
Definition at line 96 of file modular_math.h.
| typedef signed __int128 int128_t |
Pretty name for signed 128 bit integer.
GCC implements 128 bit arithmetic in terms of 64 bit arithmetic.
Definition at line 20 of file modular_math.h.
| typedef unsigned __int128 uint128_t |
Pretty name for unsigned 128 bit integer.
GCC implements 128 bit arithmetic in terms of 64 bit arithmetic.
Definition at line 23 of file modular_math.h.
| uint64_t nut_u64_pow | ( | uint64_t | b, |
| uint64_t | e | ||
| ) |
Compute nonnegative integral power of integer using binary exponentiation.
| [in] | b,e | base and exponent |
Compute nonnegative integral power of integer using binary exponentiation.
| [in] | b,e | base and exponent |
| uint64_t nut_u64_powmod | ( | uint64_t | b, |
| uint64_t | e, | ||
| uint64_t | n | ||
| ) |
Compute nonnegative integral power of a number modulo another using binary exponentiation.
| [in] | b,e,n | base, exponent, and modulus |
| uint64_t nut_u64_binom | ( | uint64_t | n, |
| uint64_t | k | ||
| ) |
Compute single binomial coefficient semi-naively.
Repeatedly does multiplications by n, n-1, n-2, ..., n-k+1 interleaved with divisions by 1, 2, 3, ..., k. Overflows quickly, look into mod m versions if using large inputs. See nut_u64_binom_next to iterate over values (n choose k), (n choose k+1). See nut_u64_binom_next_mod_2t to iterate over values mod powers of 2
| [in] | n,k | Binomial coefficient arguments |
| uint64_t nut_u64_binom_next | ( | uint64_t | n, |
| uint64_t | k, | ||
| uint64_t | prev | ||
| ) |
Compute the binomial coefficient for (n choose k) given the binomial coefficient for (n choose k-1) Simply uses the recurrence (n choose k) = (n - k + 1)/k * (n choose k-1) The starting point should be (n choose 0) = 1.
To start at k != 0, use nut_u64_binom. See nut_u64_binom_next_mod_2t to iterate over values mod powers of 2.
| [in] | n,k | Binomial coefficient arguments |
| [in] | prev | Binomial coefficient value for (n choose k-1) |
| uint64_t nut_u64_prand | ( | uint64_t | a, |
| uint64_t | b | ||
| ) |
Generate a (pseudo)random integer uniformly from [a, b).
Currently calls nut_u64_rand so this number is generated from /dev/random but this function exists to provide a weaker, pseudorandom number source if this turns out to be a bottleneck.
| [in] | a,b | bounds of the interval [a, b) |
| uint64_t nut_u64_rand | ( | uint64_t | a, |
| uint64_t | b | ||
| ) |
Generate a (strong) random integer uniformly from [a, b).
Currently uses /dev/random via the getrandom function, but this is a Linux api.
| [in] | a,b | bounds of the interval [a, b) |
| int64_t nut_i64_egcd | ( | int64_t | a, |
| int64_t | b, | ||
| int64_t *restrict | _t, | ||
| int64_t *restrict | _s | ||
| ) |
Compute d = gcd(a, b) and x, y st.
xa + by = d.
| [in] | a,b | numbers to find gcd of |
| [out] | _t,_s | pointers to output x and y to respectively (ignored if NULL) |
| int64_t nut_i64_modinv | ( | int64_t | a, |
| int64_t | b | ||
| ) |
Find the multiplicative inverse of a mod b If b is a power of 2, use nut_i64_modinv_2t Just a wrapper around nut_i64_egcd.
If a and b are not coprime, then the value returned will just be the bezout coefficient for a, and will yield gcd(a, b) when multiplied with a mod b instead of 1.
| uint64_t nut_u64_modinv_2t | ( | uint64_t | a, |
| uint64_t | t | ||
| ) |
Find the multiplicative inverse of a mod 2**t This uses a hensel/newton like iterative algorithm, described here https://crypto.stackexchange.com/a/47496 Basically, we use a lookup table to get the inverse mod 2**8, and then use the fact that ax = 1 mod 2**k --> ax(2-ax) = 1 mod 2**(2k) to lift the inverse to mod 2**16, mode 2**32, etc as needed.
This does cap out at 2**64.
| [in] | a | number to invert, MUST be odd. |
| [in] | t | Exponent of modulus, ie we want to work mod 2**t, MUST be <= 64. 0 and 1 are allowed, but won't give very interesting results. |
| int64_t nut_i64_mod | ( | int64_t | a, |
| int64_t | n | ||
| ) |
Compute the Euclidean remainder r = a mod n for positive n so that 0 <= r < n.
| [in] | a,n | dividend and divisor |
| int64_t nut_i64_crt | ( | int64_t | a, |
| int64_t | p, | ||
| int64_t | b, | ||
| int64_t | q | ||
| ) |
Compute n mod pq st n = a mod p and n = b mod q, where p and q are coprime.
| [in] | a,p,b,q | Chinese Remainder Theorem parameters. The residues a and b should not be negative. The moduli p and q should be coprime. |
| int128_t nut_i128_crt | ( | int64_t | a, |
| int64_t | p, | ||
| int64_t | b, | ||
| int64_t | q | ||
| ) |
Compute n mod pq st n = a mod p and n = b mod q, where p and q are coprime.
| [in] | a,p,b,q | Chinese Remainder Theorem parameters. The residues a and b should not be negative. The moduli p and q should be coprime. |
| int64_t nut_i64_lcm | ( | int64_t | a, |
| int64_t | b | ||
| ) |
Compute the least common multiple of a and b Divides the product by the gcd so can overflow for large arguments.
| [in] | a,b | numbers to find nut_i64_lcm of |
| uint64_t nut_u64_binom_next_mod_2t | ( | uint64_t | n, |
| uint64_t | k, | ||
| uint64_t | t, | ||
| uint64_t *restrict | v2, | ||
| uint64_t *restrict | p2 | ||
| ) |
Compute the binomial coefficient for (n choose k) given the binomial coefficient for (n choose k-1) Simply uses the recurrence (n choose k) = (n - k + 1)/k * (n choose k-1) The starting point should be (n choose 0) = 1.
To start at k != 0, use nut_u64_binom. See nut_u64_binom_next_mod_2t to iterate over values mod powers of 2.
| [in] | n,k | Binomial coefficient arguments |
| [in] | t | Exponent of modulus, ie we want to work mod 2^t |
| [in,out] | v2 | 2-adic valuation of (n choose k-1), that is, the highest power of 2 dividing (n choose k-1). This will be updated in-place, so to start from (n choose 0) it can just be initialized to 0. |
| [in,out] | p2 | 2-coprime part of (n choose k-1), that is, (n choose k-1) divided by 2^v2, This will be updated in-place, so to start from (n choose 0) it can just be initialized to 1. |
| int64_t nut_i64_jacobi | ( | int64_t | n, |
| int64_t | k | ||
| ) |
Compute the Jacobi symbol of n mod k.
Uses modified euclidean algorithm.
| [in] | n,k | Jacobi symbol parameters |
| uint64_t * nut_u64_make_jacobi_tbl | ( | uint64_t | p, |
| int64_t | partial_sums[restrict static p] | ||
| ) |
Compute the Jacobi symbol for all numbers mod a prime.
Currently the modulus must be a prime
| [in] | p | prime to compute all jacobi(r/p) modulo |
| [out] | partial_sums | buffer to store sums jacobi(0/p) + ... + jacobi(r/p) |
is_qr where the bit for positive r is 0 if r is a nonresidue (jacobi symbol -1), or 1 if r is a residue (jacobi symbol 1). If r is zero, then its jacobi symbol is 0. nut_u64_jacobi_tbl_get handles this automatically | int64_t nut_u64_jacobi_tbl_get | ( | uint64_t | n, |
| uint64_t | p, | ||
| const uint64_t | is_qr[restrict static(p+63)/64] | ||
| ) |
Convenience function to get the jacobi symbol for n from a table The table should come from nut_u64_make_jacobi_tbl.
| [in] | n | residue to find jacobi symbol for, does not need to be reduced |
| [in] | p | prime that the table was computed for |
| [in] | is_qr | table from nut_u64_make_jacobi_symbol |
| int64_t nut_i64_rand_nr_mod | ( | int64_t | p | ) |
Compute a random number mod a prime that is not a quadratic residue.
This is useful in Shanks's algorithm and others. This function works by rejection sampling using the Jacobi symbol as a test, which succeeds in 2(p-2)/(p-1) trials on average. If p is not prime, the Jacobi symbol can be positive for a nonresidue, so not all nonresidues are possible, and the number of trials on average could be larger than the prime p case.
| [in] | p | the modulus for which to generate a nonresidue. Should be prime. |
| int64_t nut_i64_sqrt_shanks | ( | int64_t | n, |
| int64_t | p | ||
| ) |
Compute the square root of a quadratic residue mod a prime.
If n is not a residue or p is not a prime, this function is not guaranteed to terminate.
| [in] | n | a quadratic residue mod p |
| [in] | p | a prime |
| int64_t nut_i64_sqrt_cipolla | ( | int64_t | n, |
| int64_t | p | ||
| ) |
Compute the square root of a quadratic residue mod a prime.
If n is not a residue or p is not a prime, the value returned may not be useful but the function will terminate.
| [in] | n | a quadratic residue mod p |
| [in] | p | a prime |
| int64_t nut_i64_sqrt_mod | ( | int64_t | n, |
| int64_t | p | ||
| ) |
Compute the square root of a quadratic residue mod a prime.
If n is not a residue or p is not a prime, this function is not guaranteed to terminate. If your use case does not guarantee this, call nut_u64_is_prime_dmr and nut_i64_jacobi beforehand. uses shortcuts for primes that are 3, 5, or 7 mod 8, otherwise uses Shanks's algorithm unless p-1 is divisible by a sufficiently high power of 2 so Cipolla's algorithm will be faster, in which case it is used. Only the Shank's branch can fail to terminate, although other branches give useless results if the preconditions are not met.
| [in] | n | a quadratic residue mod p |
| [in] | p | a prime |
| uint64_t nut_i32_fastmod_init | ( | uint32_t | pd | ) |
Compute a constant to use to do modular division faster.
| [in] | pd | absolute value of divisor |
nut_i32_fastmod | uint64_t nut_u32_fastmod_init | ( | uint32_t | d | ) |
Compute a constant to use to do modular division faster.
| [in] | d | divisor |
nut_u32_fastmod | uint128_t nut_i64_fastmod_init | ( | uint64_t | pd | ) |
Compute a constant to use to do modular division faster.
| [in] | pd | absolute value of divisor |
nut_i64_fastmod | uint128_t nut_u64_fastmod_init | ( | uint64_t | d | ) |
Compute a constant to use to do modular division faster.
| [in] | d | divisor |
nut_u64_fastmod | int32_t nut_i32_fastmod_trunc | ( | int32_t | n, |
| uint32_t | pd, | ||
| uint64_t | c | ||
| ) |
Compute n mod d, choosing the smallest signed remainder.
| [in] | n | dividend |
| [in] | pd | absolute value of divisor |
| [in] | c | constant from nut_i32_fastmod_init |
| int32_t nut_i32_fastmod_floor | ( | int32_t | n, |
| uint32_t | pd, | ||
| uint64_t | c | ||
| ) |
Compute n mod d, choosing the euclidean remainder.
| [in] | n | dividend |
| [in] | pd | absolute value of divisor |
| [in] | c | constant from nut_i32_fastmod_init |
| uint32_t nut_u32_fastmod | ( | uint32_t | n, |
| uint32_t | d, | ||
| uint64_t | c | ||
| ) |
Compute n mod d faster using a precomputed constant.
| [in] | n | dividend |
| [in] | d | divisor |
| [in] | c | constant from nut_u32_fastmod_init |
| int64_t nut_i64_fastmod_trunc | ( | int64_t | n, |
| uint64_t | pd, | ||
| uint128_t | c | ||
| ) |
Compute n mod d, choosing the smallest signed remainder.
| [in] | n | dividend |
| [in] | pd | absolute value of divisor |
| [in] | c | constant from nut_i64_fastmod_init |
| int64_t nut_i64_fastmod_floor | ( | int64_t | n, |
| uint64_t | pd, | ||
| uint128_t | c | ||
| ) |
Compute n mod d, choosing the euclidean remainder.
| [in] | n | dividend |
| [in] | pd | absolute value of divisor |
| [in] | c | constant from nut_i64_fastmod_init |
| uint64_t nut_u64_fastmod | ( | uint64_t | n, |
| uint64_t | d, | ||
| uint128_t | c | ||
| ) |
Compute n mod d faster using a precomputed constant.
| [in] | n | dividend |
| [in] | d | divisor |
| [in] | c | constant from nut_u64_fastmod_init |