From 1395b06d4ee0badd0a60f2f6b14717ed5cf648d0 Mon Sep 17 00:00:00 2001 From: Moritz Moeller Date: Tue, 9 Apr 2024 18:39:00 +0200 Subject: [PATCH 1/3] Docs: condensed int. backend docs with cargo features and added benchmarks. --- Cargo.toml | 31 +++++++++++++------ README.md | 91 ++++++++++++++++++++++++++++-------------------------- src/lib.rs | 45 +++++++++++++-------------- 3 files changed, 91 insertions(+), 76 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bccecd1..e6895dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,21 +29,34 @@ rug = { version = "1.24", optional = true, default-features = false, features = default = ["ibig", "rayon"] ## Enable parallel construction of the Voronoi grid. rayon = ["dep:rayon"] -## Allow saving Voronoi grids to -## [HDF5 format](https://en.wikipedia.org/wiki/Hierarchical_Data_Format#HDF5). -hdf5 = ["dep:hdf5"] -## Use the `dashu` crate as the arbitrary precision integer arithmetic backend. -dashu = ["dep:dashu"] -## Use the `ibig` crate as the arbitrary precision integer arithmetic backend. +## Use the `ibig` crate (MIT/Apache 2.0) as the arbitrary precision integer +## arithmetic backend. +## It generally has good performance, but can be up to 40% slower than the +## `rug` backend for highly degenerate seed configurations. ibig = ["dep:ibig"] +## Use the `dashu` crate (MIT/Apache 2.0) as the arbitrary precision integer +## arithmetic backend. +## Similar performance to the `ibig` backend. +dashu = ["dep:dashu"] ## Use the `malachite` crate as the arbitrary precision integer arithmetic backend. -## *Warning:* this changes the license to the more restrictive LGPL-3.0-only license. +## *Warning:* this changes the license to the more restrictive LGPL-3.0-only +## license. +## Slightly faster than the `dashu` backend (up to 30% slower than `rug`). malachite = ["malachite-nz", "malachite-base"] -## Use the `num_bigint` crate as the arbitrary precision integer arithmetic backend. +## Use the `num_bigint` crate (MIT/Apache 2.0) as the arbitrary precision +## integer arithmetic backend. +## Worst performance for degenerate seed configurations (measured up to 109% +## slower than `rug`). num_bigint = ["dep:num-bigint"] ## Use the `rug` crate as arbitrary precision integer arithmetic backend. -## *Warning:* this changes the license to the more restrictive LGPL-3.0+ license. +## *Warning:* this changes the license to the more restrictive LGPL-3.0+ +## license. +## The fastest backend, but depends on GNU GMP via the `gmp-mpfr-sys` crate +## which requires a C compiler to build and hence has the slowest build time. rug = ["dep:rug"] +## Allow saving Voronoi grids to +## [HDF5 format](https://en.wikipedia.org/wiki/Hierarchical_Data_Format#HDF5). +hdf5 = ["dep:hdf5"] [dev-dependencies] float-cmp = "0.9" diff --git a/README.md b/README.md index 9d158b4..d8698be 100644 --- a/README.md +++ b/README.md @@ -43,59 +43,64 @@ info: ## Integer Arithmetic Backend -You can select from five backends for arbitrary precision integer arithmetic. -These all provide identical functionality and vary only in performance and licensing. +You can select from five backends for arbitrary precision integer +arithmetic. These all provide identical functionality and vary only in +performance and licensing. -For most practical applications, the choice of backend does not significantly alter -performance. However, for highly degenerate seed configurations - i.e. with many groups of more -than 4 (almost) co-spherical seed points - many arbitrary precision arithmetic tests must be -performed leading to some performance differences in such cases. +For most practical applications, the choice of backend does not +significantly alter performance. However, for highly degenerate seed +configurations -- i.e. with many groups of more than four (almost) +co-spherical seed points -- many arbitrary precision arithmetic tests must +be performed leading to some performance differences in such cases. -- [`ibig`](https://crates.io/crates/ibig) (MIT/Apache 2.0): This is the default backend. - It generally has good performance, but can be up to 40% slower than the `rug` backend for - highly degenerate seed configurations. +Benchmarks for construction of a Voronoi grid with 35³ seeds (single +threaded): -- [`dashu`](https://crates.io/crates/dashu) (MIT/Apache 2.0): Similar performance to the `ibig` - backend. - -- [`num_bigint`](https://crates.io/crates/num-bigint) (MIT/Apache 2.0): Worst performance for - degenerate seed configurations (measured up to 109% slower than `rug`) - -- [`malachite`](https://crates.io/crates/malachite) (LGPL-3.0-only): Slightly faster than the - `dashu` backend (up to 30% slower than `rug`). +| | Perfect grid | Perturbed grid | +| ------------ | ----------------- | ------------------ | +| `rug` | 1.129 s ± 0.011 s | 705.9 ms ± 9.7 ms | +| `malachite` | 1.477 s ± 0.070 s | 702.8 ms ± 9.0 ms | +| `dashu` | 1.731 s ± 0.037 s | 735.6 ms ± 10.3 ms | +| `num-bigint` | 2.249 s ± 0.125 s | 695.2 ms ± 6.8 ms | -- [`rug`](https://crates.io/crates/rug) (LGPL-3.0+): The fastest backend, but depends on GNU GMP - via the `gmp-mpfr-sys` crate which requires a C compiler to build and hence has the slowest - build time. +See the next section for details. ## Cargo Features -- `rayon` (enabled by default) – Enable parallel construction of the Voronoi - grid. - -- `hdf5` – Allow saving Voronoi grids to [HDF5 format](https://en.wikipedia.org/wiki/Hierarchical_Data_Format#HDF5). - -- `dashu` — Use the `dashu` crate as the arbitrary precision integer arithmetic backend. - -- `ibig` (enabled by default) — Use the `ibig` crate as the arbitrary precision integer arithmetic backend. -- `malachite` — Use the `malachite` crate as the arbitrary precision integer arithmetic backend. - - *Disclaimer*: this changes the license to the more restrictive LGPL-3.0-only license. - -- `num_bigint` — Use the `num_bigint` crate as the arbitrary precision integer arithmetic backend. - -- `rug` – Use the `rug` crate as the arbitrary precision integer arithmetic backend. - This can increase performance significantly for highly degenerate seed configurations where lots of arbitrary - precision arithmetic is needed. - - *Disclaimer:* this changes the license to the more restrictive LGPL-3.0+ license. +- `rayon` -- Enable parallel construction of the Voronoi grid. +- `ibig` -- Use the `ibig` crate (MIT/Apache 2.0) as the arbitrary precision + integer arithmetic backend. + It generally has good performance, but can be up to 40% slower than the + `rug` backend for highly degenerate seed configurations. +- `dashu` -- Use the `dashu` crate (MIT/Apache 2.0) as the arbitrary precision + integer arithmetic backend. + Similar performance to the `ibig` backend. +- `malachite` -- Use the `malachite` crate as the arbitrary precision integer + arithmetic backend. + *Warning:* this changes the license to the more restrictive LGPL-3.0-only + license. + Slightly faster than the `dashu` backend (up to 30% slower than `rug`). +- `num_bigint` -- Use the `num_bigint` crate (MIT/Apache 2.0) as the arbitrary + precision integer arithmetic backend. + Worst performance for degenerate seed configurations (measured up to 109% + slower than `rug`). +- `rug` -- Use the `rug` crate as arbitrary precision integer arithmetic + backend. + *Warning:* this changes the license to the more restrictive LGPL-3.0+ license. + The fastest backend, but depends on GNU GMP via the `gmp-mpfr-sys` crate which + requires a C compiler to build and hence has the slowest build time. +- `hdf5` -- Allow saving Voronoi grids to ## License Licensed under: - - [Apache-2.0](www.apache.org/licenses/LICENSE-2.0) OR [MIT](https://opensource.org/license/MIT) at your option when - using the `ibig`, `dashu` or `num_bigint` arbitrary precision arithmetic backends. - - [LGPL-3.0-only](https://www.gnu.org/licenses/lgpl-3.0.html) when using the `malachite` backend - - [LGPL-3.0+](https://www.gnu.org/licenses/lgpl-3.0.html) when using the `rug` backend. + +- [Apache-2.0](www.apache.org/licenses/LICENSE-2.0) OR + [MIT](https://opensource.org/license/MIT) at your option when using the + `ibig`, `dashu` or `num_bigint` arbitrary precision arithmetic backends. +- [LGPL-3.0-only](https://www.gnu.org/licenses/lgpl-3.0.html) when using the + `malachite` backend +- [LGPL-3.0+](https://www.gnu.org/licenses/lgpl-3.0.html) when using the `rug` + backend. diff --git a/src/lib.rs b/src/lib.rs index 44a44df..7035928 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,30 +40,27 @@ //! //! # Integer Arithmetic Backend //! -//! You can select from five backends for arbitrary precision integer arithmetic. -//! These all provide identical functionality and vary only in performance and licensing. -//! -//! For most practical applications, the choice of backend does not significantly alter -//! performance. However, for highly degenerate seed configurations - i.e. with many groups of more -//! than 4 (almost) co-spherical seed points - many arbitrary precision arithmetic tests must be -//! performed leading to some performance differences in such cases. -//! -//! - [`ibig`](https://crates.io/crates/ibig) (MIT/Apache 2.0): This is the default backend. -//! It generally has good performance, but can be up to 40% slower than the `rug` backend for -//! highly degenerate seed configurations. -//! -//! - [`dashu`](https://crates.io/crates/dashu) (MIT/Apache 2.0): Similar performance to the `ibig` -//! backend. -//! -//! - [`num_bigint`](https://crates.io/crates/num-bigint) (MIT/Apache 2.0): Worst performance for -//! degenerate seed configurations (measured up to 109% slower than `rug`) -//! -//! - [`malachite`](https://crates.io/crates/malachite) (LGPL-3.0-only): Slightly faster than the -//! `dashu` backend (up to 30% slower than `rug`). -//! -//! - [`rug`](https://crates.io/crates/rug) (LGPL-3.0+): The fastest backend, but depends on GNU GMP -//! via the `gmp-mpfr-sys` crate which requires a C compiler to build and hence has the slowest -//! build time. +//! You can select from five backends for arbitrary precision integer +//! arithmetic. These all provide identical functionality and vary only in +//! performance and licensing. +//! +//! For most practical applications, the choice of backend does not +//! significantly alter performance. However, for highly degenerate seed +//! configurations -- i.e. with many groups of more than four (almost) +//! co-spherical seed points -- many arbitrary precision arithmetic tests must +//! be performed leading to some performance differences in such cases. +//! +//! Benchmarks for construction of a Voronoi grid with 35³ seeds (single +//! threaded): +//! +//! | | Perfect grid | Perturbed grid | +//! | ------------ | ----------------- | ------------------ | +//! | `rug` | 1.129 s ± 0.011 s | 705.9 ms ± 9.7 ms | +//! | `malachite` | 1.477 s ± 0.070 s | 702.8 ms ± 9.0 ms | +//! | `dashu` | 1.731 s ± 0.037 s | 735.6 ms ± 10.3 ms | +//! | `num-bigint` | 2.249 s ± 0.125 s | 695.2 ms ± 6.8 ms | +//! +//! See the next section for details. //! //! # Cargo Features #![doc = document_features::document_features!()] From 6ce4b9cf63dd5f1fa9be5cfdcf9a8d23b5bd69f6 Mon Sep 17 00:00:00 2001 From: Yolan Uyttenhove Date: Wed, 10 Apr 2024 11:04:37 +0200 Subject: [PATCH 2/3] add example/benchmark + export Dimensionality + rename test modules --- examples/grid_3d.rs | 62 +++++++++++++++++++++++++++++++++++++ src/bounding_sphere.rs | 2 +- src/geometry.rs | 2 +- src/lib.rs | 4 ++- src/simple_cycle.rs | 2 +- src/util.rs | 2 +- src/voronoi.rs | 4 +-- src/voronoi/convex_cell.rs | 2 +- src/voronoi/voronoi_cell.rs | 2 +- 9 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 examples/grid_3d.rs diff --git a/examples/grid_3d.rs b/examples/grid_3d.rs new file mode 100644 index 0000000..b811620 --- /dev/null +++ b/examples/grid_3d.rs @@ -0,0 +1,62 @@ +//! Example that builds a Voronoi tesselation for a (perturbed) grid of n^3 points in 3 dimensions. +//! +//! Run with: `cargo run --release --example grid_3d` +//! +//! The number of points and the size of perturbations can optionally be given as command line +//! arguments: `cargo run --release --example grid_3d -- [n] [p]` +//! +//! Their default values are: +//! - `n`: 64 +//! - `p`: 0.95 + +extern crate glam; +extern crate meshless_voronoi; +extern crate rand; + +use glam::DVec3; +use meshless_voronoi::Voronoi; +use rand::{distributions::Uniform, prelude::*}; +use std::convert::TryInto; +use std::env; + +fn perturbed_grid(anchor: DVec3, width: DVec3, count: usize, pert: f64) -> Vec { + let mut generators = vec![]; + let mut rng = thread_rng(); + let distr = Uniform::new(-0.5, 0.5); + for n in 0..count.pow(3) { + let i = n / count.pow(2); + let j = (n % count.pow(2)) / count; + let k = n % count; + let pos = DVec3 { + x: i as f64 + 0.5 + pert * rng.sample(distr), + y: j as f64 + 0.5 + pert * rng.sample(distr), + z: k as f64 + 0.5 + pert * rng.sample(distr), + } * width + / count as f64 + + anchor; + generators.push(pos.clamp(anchor, anchor + width)); + } + + generators +} + +fn main() { + let mut args = env::args().skip(1); + let count = match args.next() { + Some(n) => n.parse::().expect( + "The first argument should be an integer denoting the grid size along one dimension!", + ), + None => 64, + }; + let pert = match args.next() { + Some(p) => p.parse::().expect( + "The second argument should be a number between 0 and 1 denoting the size of the grid perturbations!" + ), + None => 0.95, + }; + + let anchor = DVec3::splat(0.); + let width = DVec3::splat(1.); + let generators = perturbed_grid(anchor, width, count, pert); + let _voronoi = Voronoi::build(&generators, anchor, width, 3.try_into().unwrap(), false); +} diff --git a/src/bounding_sphere.rs b/src/bounding_sphere.rs index 13b6cce..98984c3 100644 --- a/src/bounding_sphere.rs +++ b/src/bounding_sphere.rs @@ -154,7 +154,7 @@ impl BoundingSphereSolver for Epos6 { } #[cfg(test)] -mod test { +mod tests { use glam::DVec3; use super::{BoundingSphereSolver, Epos6, Welzl}; diff --git a/src/geometry.rs b/src/geometry.rs index 3eae081..cf3f406 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -352,7 +352,7 @@ impl Aabb { } #[cfg(test)] -mod test { +mod tests { use glam::DVec3; use crate::geometry::{signed_area_tri, signed_volume_tet}; diff --git a/src/lib.rs b/src/lib.rs index 44a44df..0cdf023 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,4 +102,6 @@ mod space; mod util; mod voronoi; -pub use voronoi::{integrals, ConvexCell, Voronoi, VoronoiCell, VoronoiFace, VoronoiIntegrator}; +pub use voronoi::{ + integrals, ConvexCell, Dimensionality, Voronoi, VoronoiCell, VoronoiFace, VoronoiIntegrator, +}; diff --git a/src/simple_cycle.rs b/src/simple_cycle.rs index f1b5e1d..c79ed15 100644 --- a/src/simple_cycle.rs +++ b/src/simple_cycle.rs @@ -101,7 +101,7 @@ impl<'a> Iterator for SimpleCycle2Iterator<'a> { } #[cfg(test)] -mod test { +mod tests { use crate::simple_cycle::SimpleCycle; #[test] diff --git a/src/util.rs b/src/util.rs index b445242..b846852 100644 --- a/src/util.rs +++ b/src/util.rs @@ -44,7 +44,7 @@ impl GetMutMultiple for Vec { } #[cfg(test)] -mod test { +mod tests { use super::*; #[test] diff --git a/src/voronoi.rs b/src/voronoi.rs index 3c6c437..59328cd 100644 --- a/src/voronoi.rs +++ b/src/voronoi.rs @@ -26,7 +26,7 @@ mod voronoi_cell; mod voronoi_face; /// The dimensionality of the Voronoi tessellation. -#[derive(Clone, Copy, Debug, PartialEq, num_enum::IntoPrimitive)] +#[derive(Clone, Copy, Debug, PartialEq, num_enum::IntoPrimitive, num_enum::TryFromPrimitive)] #[repr(usize)] pub enum Dimensionality { OneD = 1, @@ -604,7 +604,7 @@ impl VoronoiIntegrator { } #[cfg(test)] -mod test { +mod tests { use super::{ integrals::{AreaCentroidIntegrator, VolumeCentroidIntegrator}, *, diff --git a/src/voronoi/convex_cell.rs b/src/voronoi/convex_cell.rs index 5ef561e..15a45fe 100644 --- a/src/voronoi/convex_cell.rs +++ b/src/voronoi/convex_cell.rs @@ -474,7 +474,7 @@ impl From for ConvexCell { } #[cfg(test)] -mod test { +mod tests { use super::*; #[test] diff --git a/src/voronoi/voronoi_cell.rs b/src/voronoi/voronoi_cell.rs index d8c729a..117fc00 100644 --- a/src/voronoi/voronoi_cell.rs +++ b/src/voronoi/voronoi_cell.rs @@ -170,4 +170,4 @@ impl VoronoiCell { } #[cfg(test)] -mod test {} +mod tests {} From a4c83b5a8cd3bc518acdcea0383ccae1a31730f9 Mon Sep 17 00:00:00 2001 From: Yolan Uyttenhove Date: Wed, 10 Apr 2024 11:22:54 +0200 Subject: [PATCH 3/3] update benchmark results --- Cargo.toml | 8 ++++---- README.md | 37 ++++++++++++++++++++----------------- src/lib.rs | 31 +++++++++++++++++-------------- 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e6895dd..feb9dbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,8 +31,8 @@ default = ["ibig", "rayon"] rayon = ["dep:rayon"] ## Use the `ibig` crate (MIT/Apache 2.0) as the arbitrary precision integer ## arithmetic backend. -## It generally has good performance, but can be up to 40% slower than the -## `rug` backend for highly degenerate seed configurations. +## It generally has good performance, but can be up to 50% slower than the +## `rug` backend for highly degenerate seed configurations (e.g. a perfect grid). ibig = ["dep:ibig"] ## Use the `dashu` crate (MIT/Apache 2.0) as the arbitrary precision integer ## arithmetic backend. @@ -41,11 +41,11 @@ dashu = ["dep:dashu"] ## Use the `malachite` crate as the arbitrary precision integer arithmetic backend. ## *Warning:* this changes the license to the more restrictive LGPL-3.0-only ## license. -## Slightly faster than the `dashu` backend (up to 30% slower than `rug`). +## Slightly faster than the `dashu` backend (up to 40% slower than `rug`). malachite = ["malachite-nz", "malachite-base"] ## Use the `num_bigint` crate (MIT/Apache 2.0) as the arbitrary precision ## integer arithmetic backend. -## Worst performance for degenerate seed configurations (measured up to 109% +## Worst performance for degenerate seed configurations (measured up to 140% ## slower than `rug`). num_bigint = ["dep:num-bigint"] ## Use the `rug` crate as arbitrary precision integer arithmetic backend. diff --git a/README.md b/README.md index d8698be..288e721 100644 --- a/README.md +++ b/README.md @@ -48,31 +48,34 @@ arithmetic. These all provide identical functionality and vary only in performance and licensing. For most practical applications, the choice of backend does not -significantly alter performance. However, for highly degenerate seed -configurations -- i.e. with many groups of more than four (almost) -co-spherical seed points -- many arbitrary precision arithmetic tests must -be performed leading to some performance differences in such cases. - -Benchmarks for construction of a Voronoi grid with 35³ seeds (single -threaded): - -| | Perfect grid | Perturbed grid | -| ------------ | ----------------- | ------------------ | -| `rug` | 1.129 s ± 0.011 s | 705.9 ms ± 9.7 ms | -| `malachite` | 1.477 s ± 0.070 s | 702.8 ms ± 9.0 ms | -| `dashu` | 1.731 s ± 0.037 s | 735.6 ms ± 10.3 ms | -| `num-bigint` | 2.249 s ± 0.125 s | 695.2 ms ± 6.8 ms | +significantly alter performance (see results for a perturbed grid below). +However, for highly degenerate seed configurations -- i.e. with many groups +of more than four (almost) co-spherical seed points -- many arbitrary precision +arithmetic tests must be performed leading to some performance differences +in such cases (see results for a perfect grid below). + +Benchmarks for construction of a 3D Voronoi grid with 64³ seeds: + +| | Perfect grid | Perturbed grid | +| ------------ | ----------------- | ----------------- | +| `rug` | 2.062 s ± 0.005 s | 1.308 s ± 0.008 s | +| `malachite` | 2.846 s ± 0.016 s | 1.293 s ± 0.005 s | +| `ibig` | 3.105 s ± 0.048 s | 1.320 s ± 0.022 s | +| `dashu` | 3.249 s ± 0.091 s | 1.313 s ± 0.009 s | +| `num-bigint` | 4.852 s ± 0.078 s | 1.301 s ± 0.004 s | See the next section for details. ## Cargo Features +**Note**: the features for choosing a backend are all *mutually exclusive*. + - `rayon` -- Enable parallel construction of the Voronoi grid. - `ibig` -- Use the `ibig` crate (MIT/Apache 2.0) as the arbitrary precision integer arithmetic backend. - It generally has good performance, but can be up to 40% slower than the + It generally has good performance, but can be up to 50% slower than the `rug` backend for highly degenerate seed configurations. - `dashu` -- Use the `dashu` crate (MIT/Apache 2.0) as the arbitrary precision integer arithmetic backend. @@ -81,10 +84,10 @@ See the next section for details. arithmetic backend. *Warning:* this changes the license to the more restrictive LGPL-3.0-only license. - Slightly faster than the `dashu` backend (up to 30% slower than `rug`). + Slightly faster than the `dashu` backend (up to 40% slower than `rug`). - `num_bigint` -- Use the `num_bigint` crate (MIT/Apache 2.0) as the arbitrary precision integer arithmetic backend. - Worst performance for degenerate seed configurations (measured up to 109% + Worst performance for degenerate seed configurations (measured up to 140% slower than `rug`). - `rug` -- Use the `rug` crate as arbitrary precision integer arithmetic backend. diff --git a/src/lib.rs b/src/lib.rs index b0027a7..1b9c9a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,24 +45,27 @@ //! performance and licensing. //! //! For most practical applications, the choice of backend does not -//! significantly alter performance. However, for highly degenerate seed -//! configurations -- i.e. with many groups of more than four (almost) -//! co-spherical seed points -- many arbitrary precision arithmetic tests must -//! be performed leading to some performance differences in such cases. -//! -//! Benchmarks for construction of a Voronoi grid with 35³ seeds (single -//! threaded): -//! -//! | | Perfect grid | Perturbed grid | -//! | ------------ | ----------------- | ------------------ | -//! | `rug` | 1.129 s ± 0.011 s | 705.9 ms ± 9.7 ms | -//! | `malachite` | 1.477 s ± 0.070 s | 702.8 ms ± 9.0 ms | -//! | `dashu` | 1.731 s ± 0.037 s | 735.6 ms ± 10.3 ms | -//! | `num-bigint` | 2.249 s ± 0.125 s | 695.2 ms ± 6.8 ms | +//! significantly alter performance (see results for a perturbed grid below). +//! However, for highly degenerate seed configurations -- i.e. with many groups +//! of more than four (almost) co-spherical seed points -- many arbitrary precision +//! arithmetic tests must be performed leading to some performance differences +//! in such cases (see results for a perfect grid below). +//! +//! Benchmarks for construction of a 3D Voronoi grid with 64³ seeds: +//! +//! | | Perfect grid | Perturbed grid | +//! | ------------ | ----------------- | ----------------- | +//! | `rug` | 2.062 s ± 0.005 s | 1.308 s ± 0.008 s | +//! | `malachite` | 2.846 s ± 0.016 s | 1.293 s ± 0.005 s | +//! | `ibig` | 3.105 s ± 0.048 s | 1.320 s ± 0.022 s | +//! | `dashu` | 3.249 s ± 0.091 s | 1.313 s ± 0.009 s | +//! | `num-bigint` | 4.852 s ± 0.078 s | 1.301 s ± 0.004 s | //! //! See the next section for details. //! //! # Cargo Features +//! +//! **Note**: the features for choosing a backend are all *mutually exclusive*. #![doc = document_features::document_features!()] #[cfg(any(