Expand description
Fast arithmetic modulo 2^k, 2^k - 1, and 2^k - d.
Modular arithmetic is useful for fast hashing, verification of polynomial operations, and as a ring balancing the cost of division with the cost of other operations. Different moduli make different quality vs performance tradeoffs:
- Big prime moduli have the best quality, but operations are quite slow due to the complexity of reduction, even if tricks like Montgomery multiplication are used.
- Primes like
2^61 - 1can be reduced significantly faster, but they are relatively rare, so you can lose several bits of precision compared to the largest prime fitting in the data type. - Moduli like
2^64 - 1support even faster implementations, but aren’t prime. Still, their factorization is non-trivial and contains somewhat large primes, so their quality may be tolerable. - Power-of-two moduli are the fastest, but have seed-independent collisions and do not support division by two.
This crate provides a uniform interface to highly optimized implementations of all these moduli, enabling you to easily try different options and find the best one. The supported moduli are:
- “Big” primes:
2^8 - 5,2^16 - 15,2^32 - 5,2^64 - 59. - Primes:
2^7 - 1,2^13 - 1,2^31 - 1,2^61 - 1. - “Fast”:
2^8 - 1,2^16 - 1,2^32 - 1,2^64 - 1. - Powers of two:
2^8,2^16,2^32,2^64.
A performance comparison table is available. mod2k is estimated to be ~2x
faster than general-purpose modular arithmetic libraries on average. More specifically,
- Power-of-two moduli are the fastest.
- “Fast” moduli are almost as fast, usually paying a cost of 1-3 additional instructions per
operation compared to power-of-two moduli, but inversion is much slower. As an exception to
the general rule that “fast” moduli are faster than primes, “fast” moduli also have the
slowest implementation of
is_invertible. - Moduli in
primehave significantly slower multiplication, but the rest of arithmetic is only slightly slower than that of “fast” moduli. - Moduli in
big_primehave even slower multiplication, and the performance of shifts is degraded to general-purpose multiplication.
§API
All types in this crate implement the Mod trait. With Mod and built-in operations, you
have access to most primitive operations:
+,-(both binary and unary), and*work straightforwardly.inversecomputes the multiplicative inverse if it exists, i.e. if the argumentxand the modulus are coprime.x / ycomputes the product ofxand the multiplicative inverse ofy. Ifyis not invertible, this operation panics. Note that computing inverses is slow, so they should ideally computed once and then reused.powcomputes exponents.<<and>>correspond to multiplication and division by powers of two, respectively. Arbitrarily large shift amounts are supported. Negative amounts correspond to the opposite operation. (Division is not supported for2^kmoduli.)==performs modular comparison.Displayand related traits print the remainder.
§Example
use mod2k::{Mod, Prime31}; // arithmetic modulo 2^31 - 1 = 2147483647
assert_eq!(Prime31::new(5) + Prime31::new(7), Prime31::new(12));
assert_eq!((-Prime31::ONE) * (-Prime31::ONE), Prime31::ONE);
assert_eq!((-Prime31::ONE).remainder(), Prime31::MODULUS - 1);§Bare metal support
This is a #![no_std] crate.
Re-exports§
Modules§
- big_
prime - Arithmetic modulo
2^8 - 5,2^16 - 15,2^32 - 5, and2^64 - 59. - fast
- Arithmetic modulo
2^8 - 1,2^16 - 1,2^32 - 1, and2^64 - 1. - power
- Arithmetic modulo
2^8,2^16,2^32, and2^64. - prime
- Arithmetic modulo
2^7 - 1,2^13 - 1,2^31 - 1, and2^61 - 1.
Traits§
- Mod
- A common interface for modular arithmetic.