This commit overrides default implementations of
Roots::sqrt and Roots::cbrt for BigInt and BigUint
with optimized ones. It also improves tests and
resolves minor inconsistencies.
Signed-off-by: Manca Bizjak <manca.bizjak@xlab.si>
This commit implements num-integer::Roots trait
for BigInt and BigUint types, and also adds sqrt,
cbrt, nth_root as inherent methods to allow access
to them without importing Roots trait. For each
type tests were added as submodules in the roots
test module.
Signed-off-by: Manca Bizjak <manca.bizjak@xlab.si>
53: switch gen_biguint to fill_bytes r=cuviper a=TheIronBorn
Changes `gen_biguint` from a `push(gen::<u32>)` method to rand's [`fill_bytes`](https://docs.rs/rand/0.5.0/rand/trait.RngCore.html#tymethod.fill_bytes). This should improve performance in most cases.
- For small PRNGs which only natively generate 64 bits (like Xorshift64 or [`splitmix64.c`](http://prng.di.unimi.it/splitmix64.c)), this will no longer throw away half the bits generated.
- For block PRNGs like `StdRng`, this should reduce overhead.
- For an SIMD PRNG (https://github.com/rust-lang-nursery/rand/issues/377), this would be a significant improvement.
```diff,ignore
name no_fill ns/iter fill ns/iter diff ns/iter diff % speedup
+rand_1009 256 222 -34 -13.28% x 1.15
+rand_131072 27,366 14,715 -12,651 -46.23% x 1.86
+rand_2048 459 357 -102 -22.22% x 1.29
-rand_256 93 130 37 39.78% x 0.72
+rand_4096 842 557 -285 -33.85% x 1.51
-rand_64 69 92 23 33.33% x 0.75
+rand_65536 13,625 7,382 -6,243 -45.82% x 1.85
+rand_8192 1,836 869 -967 -52.67% x 2.11
```
(i.e. `rand_1009` does `gen_biguint(1009)`. All benches are powers of two except `rand_1009`)
(Let me know if you want the `rand_` benches added)
Co-authored-by: TheIronBorn <>
Co-authored-by: Josh Stone <cuviper@gmail.com>
52: Make sure benchmarks can be built r=cuviper a=cuviper
This fixes the rand seeds, and builds benches in nightly CI.
Co-authored-by: Josh Stone <cuviper@gmail.com>
48: Update to rand 0.5 r=cuviper a=cuviper
This closes#47, choosing to *only* support rand 0.5 (and only for their supported rustc 1.22+).
The `RandBigInt` trait still exists as an extension to all `Rng` types. It's no longer defined at all when the "rand" feature is not enabled. That was a misbehavior before, as enabling "rand" adds a blanket implementation, which would be a breaking change just by toggling the feature.
`BigUint` and `BigInt` now implement `SampleUniform` too, which lets them work natively with `Rng::gen_range`, `Rng::sample`, and `Uniform` in general.
Co-authored-by: Josh Stone <cuviper@gmail.com>
45: Document Toom3 algorithm r=cuviper a=tiehuis
Happened to be going through toom3 so thought I'd type this up.
Co-authored-by: Marc Tiehuis <marctiehuis@gmail.com>
46: Add a mandatory "std" feature r=cuviper a=cuviper
We don't actually support `no_std` yet, and probably won't until `alloc`
is stable. We're just reserving this ability with the "std" feature
now, and compilation will fail without.
Co-authored-by: Josh Stone <cuviper@gmail.com>
We don't actually support `no_std` yet, and probably won't until `alloc`
is stable. We're just reserving this ability with the "std" feature
now, and compilation will fail without.
42: Add a special case for single-digit divisors r=cuviper a=cuviper
It was pointed out in the blog post [Big Integers in Zig] that we don't
have a special case in `num-bigint` for single-digit divisors. While
you can already get this optimization by dividing directly by `u32`,
it's easy to make small `BigUint` divisors work like this too.
$ cargo benchcmp baseline single-div
name baseline ns/iter single-div ns/iter diff ns/iter diff % speedup
factorial_div_biguint 5,638,353 1,005,488 -4,632,865 -82.17% x 5.61
`BigInt` will also gain from this, since it uses `BigUint` division
internally.
Running [zig-bn's facdiv-rs] shows a nice improvement too. My i7-7700K
with Rust 1.26 goes from 4.15 seconds to just 0.65 -- a 6.38x speedup!
[Big Integers in Zig]: https://tiehuis.github.io/big-integers-in-zig#division-test-single-limb
[zig-bn's facdiv-rs]: https://github.com/tiehuis/zig-bn/tree/master/bench/facdiv/crate-facdiv-rs
Co-authored-by: Josh Stone <cuviper@gmail.com>
It was pointed out in the blog post [Big Integers in Zig] that we don't
have a special case in `num-bigint` for single-digit divisors. While
you can already get this optimization by dividing directly by `u32`,
it's easy to make small `BigUint` divisors work like this too.
$ cargo benchcmp baseline single-div
name baseline ns/iter single-div ns/iter diff ns/iter diff % speedup
factorial_div_biguint 5,638,353 1,005,488 -4,632,865 -82.17% x 5.61
`BigInt` will also gain from this, since it uses `BigUint` division
internally.
Running [zig-bn's facdiv-rs] shows a nice improvement too. My i7-7700K
with Rust 1.26 goes from 4.15 seconds to just 0.65 -- a 6.38x speedup!
[Big Integers in Zig]: https://tiehuis.github.io/big-integers-in-zig#division-test-single-limb
[zig-bn's facdiv-rs]: https://github.com/tiehuis/zig-bn/tree/master/bench/facdiv/crate-facdiv-rs
41: Implement assignment operators for BigInt r=cuviper a=cuviper
All of these operators were already implemented for `BigUint`, so
now `BigInt` support the same use.
Closes#7.
Co-authored-by: Josh Stone <cuviper@gmail.com>
39: Make it explicit that serialization is in u32 r=cuviper a=cuviper
Add explicit type annotations to make sure we serialize `BigUint` like a
`Vec<u32>`. If we ever change the internal representation, we still
need to remain compatible with serialized data.
Also, deserializing `BigUint` and `BigInt` now uses their normal
constructor methods, to make sure they are normalized. We shouldn't
assume that all incoming data is already well-formed.
Co-authored-by: Josh Stone <cuviper@gmail.com>
Add explicit type annotations to make sure we serialize `BigUint` like a
`Vec<u32>`. If we ever change the internal representation, we still
need to remain compatible with serialized data.
Also, deserializing `BigUint` and `BigInt` now uses their normal
constructor methods, to make sure they are normalized. We shouldn't
assume that all incoming data is already well-formed.
38: Remove big_digit::* from the public API r=cuviper a=cuviper
The *idea* of `big_digit` and its type aliases is that we may someday
use something other than `u32` in the representation, perhaps even
different sizes for different targets. That's still a possibility, but
I think it's not really feasible to expose this variation in the public
API. Calling `BigUint::from_slice([1, 2, 3])` is only meaningful if you
know what that size is, and users can't really alternate this kind of
thing based on a type definition. So for now, we just commit to `u32`
units in the public API, no matter what we may do internally.
This removal is a breaking change, part of the 0.2 semver bump. If I'm
wrong and somebody can show a compelling use case for `big_digit`, we
can always add things back into the public API later.
Co-authored-by: Josh Stone <cuviper@gmail.com>