-
Notifications
You must be signed in to change notification settings - Fork 188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement Stein's algorithm for gcd #15
Conversation
This patch also adds a private
|
Ah, yes, num-integer already uses Stein's for the primitive integers, so this sounds good to me. FWIW, I have |
Without testing, I'm pretty sure that your implementation is faster or can be made to be faster. If you switch out that Probably worth it for cpus without |
Multiplying by BITS should get optimized as a simple left shift, maybe even |
I meant that without the multiplication our two versions do identical work except that my code also does a superfluous |
the methods are implemented on the types directly since rust 1.23 the trait's still needed for backwards compatibility
same asymptotic complexity as euclidean but faster thanks to bitshifts and subtractions rather than division
I added an optimization to shr that eliminated most of the allocation overhead. Thanks for the PR! bors r+ |
15: Implement Stein's algorithm for gcd r=cuviper a=Emerentius This implements Stein's algorithm for bigints. Asymptotically this has the same runtime complexity as the euclidean algorithm but it's faster because it avoids division in favor of bitshifts and subtractions. There are faster algorithms for large bigints. For small ones, [gmp uses the binary gcd too](https://gmplib.org/manual/Binary-GCD.html). I've run some benchmarks with the code in [this repo](https://github.com/Emerentius/bigint_gcd_bench) This iterates through the sizes of 1-10 `BigDigit`s and generates 300 uniformly distributed random bigints at each size and computes the gcd for each combination with both Euclid's and Stein's algorithm. I'm only looking at combinations of numbers with the same number of `BigDigit`s The speed gains are sizeable. See the benchmark results below. I'm running this on an ultrabook with a 15W CPU (i5 4210u). Performance may differ on different architectures, in particular if there is no intrinsic for counting trailing zeroes. Please run the benchmark on your machine. It's just a simple ``` git clone https://github.com/Emerentius/bigint_gcd_bench cargo run --release ``` ``` 2^32n bits euclidean gcd binary gcd speedup n: 1 => 0.3050s 0.0728s 4.19 n: 2 => 0.6228s 0.1453s 4.29 n: 3 => 0.9618s 0.2214s 4.34 n: 4 => 1.3021s 0.3028s 4.30 n: 5 => 1.6469s 0.3875s 4.25 n: 6 => 2.0017s 0.4759s 4.21 n: 7 => 2.3636s 0.5667s 4.17 n: 8 => 2.7284s 0.6418s 4.25 n: 9 => 3.0712s 0.7302s 4.21 n: 10 => 3.4822s 0.8223s 4.23 ``` The guys at gmp say these algorithms are quadratic in N, I'm not sure why they seem almost linear here.
Build succeeded |
This implements Stein's algorithm for bigints.
Asymptotically this has the same runtime complexity as the euclidean algorithm but it's faster because it avoids division in favor of bitshifts and subtractions.
There are faster algorithms for large bigints. For small ones, gmp uses the binary gcd too.
I've run some benchmarks with the code in this repo
This iterates through the sizes of 1-10
BigDigit
s and generates 300 uniformly distributed random bigints at each size and computes the gcd for each combination with both Euclid's and Stein's algorithm. I'm only looking at combinations of numbers with the same number ofBigDigit
sThe speed gains are sizeable. See the benchmark results below. I'm running this on an ultrabook with a 15W CPU (i5 4210u). Performance may differ on different architectures, in particular if there is no intrinsic for counting trailing zeroes.
Please run the benchmark on your machine. It's just a simple
The guys at gmp say these algorithms are quadratic in N, I'm not sure why they seem almost linear here.