Malachite 0.3.0: better performance and interface improvements
Last week I released version 0.3.0 of Malachite, a library for arbitrary-precision arithmetic. With this update, Malachite is now the fastest arbitrary-precision arithmetic library written in pure Rust. Here are the three major changes:
- I've rewritten the code for FFT multiplication. It was initially based on the GMP implementation and now it's based on the FLINT implementation. This has improved Malachite's performance in the Rust bigint benchmarks. Here's a side-by-side comparison (times are in seconds):
| benchmark | Malachite 0.2.2 | Malachite 0.3.0 |
|---|---|---|
| e 100k | 0.063 | 0.043 |
| e 1m | 1.356 | 0.929 |
| e 10m | 28.604 | 15.798 |
| fib 10m | 1.832 | 1.197 |
| fib 100m | 43.695 | 21.473 |
| fib\_hex 100m | 11.737 | 3.270 |
- There is now a meta-crate called
malachitewhich re-exports three sub-crates. That means that instead of importing the three sub-crates you can just importmalachite, and do things likeuse malachite::Naturalrather thanuse malachite_nz::natural::Natural. This is a backwards-compatible change; you can still do imports the old way. Thanks to Andlon for the suggestion. - When I first started writing Malachite, the
TryFromtrait didn't exist, so I created aCheckedFromtrait based on the standard library'schecked_add,checked_mul, etc., functions. Like those functions, it returned anOption. In 0.3.0, I've replacedCheckedFromwithTryFromeverywhere; this is a breaking change. Some notes:- Older versions of Malachite implemented
CheckedFrombetween primitive integers and floats. The standard library does not do this withTryFrom, and due to the orphan rule I cannot implement them in Malachite. Luckily Malachite hasNiceFloat, a wrapper around floats that gives them alternative behavior for equality, order, hashing, and formatting; I've put the conversions between primitive integers and floats there, so you can doNiceFloat::<f64>::try_from(1000u32)andu32::try_from(NiceFloat(1000.0f64)). - Andlon also pointed out the my
Fromimplementations from primitive floats toRationalcould panic (when the float is NaN or infinite), which violates theFromcontract. I've removed these implementations. I had to remove theFromimplementations fromRationalto primitive floats as well, because it's not possible to have bothTryFromandFromimplementations between the same pair of types (I believe this is because definingFrominvokes the blanket implementation ofTryFrom, which clashes with any other implementation ofTryFrom). To recover the behavior of the oldFromimplementations from primitive floats toRational, you can use e.g.Rational::exact_from(1000.0f64)(which is defined to beRational::try_from(1000.0f64).unwrap()). To recover the behavior of the oldFromimplementations fromRationalto primitive floats, you can use e.g.f64::rounding_from(Rational::from_unsigneds(1, 3), RoundingMode::Nearest). - Malachite still has
WrappingFrom,SaturatingFrom, andOverflowingFrom, since these do not have equivalents in the standard library.
- Older versions of Malachite implemented
I'm currently working on Malachite 0.3.1, which will include efficient prime number generation (all 203,280,221 u32 primes in 4.3 seconds), primorials, and binomial coefficients. 0.3.2 will include Fibonacci and Lucas numbers, and the version after that (which will probably be 0.4.0) will have an initial implementation of arbitrary-precision floats!