From a2d9093d3be8cb25d6651e9bf0117dc79c78c8b3 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 18 Jul 2023 00:19:27 +0200 Subject: [PATCH] chore: extract inline benches to a separate directory --- .cargo/config.toml | 3 - .github/workflows/ci.yml | 2 +- Cargo.lock | 152 ++++++++++--------- Cargo.toml | 26 +--- benches/bench.rs | 19 +++ benches/benches/add.rs | 46 ++++++ benches/benches/algorithms/div/mod.rs | 7 + benches/benches/algorithms/div/reciprocal.rs | 41 +++++ benches/benches/algorithms/div/small.rs | 103 +++++++++++++ benches/benches/algorithms/gcd.rs | 65 ++++++++ benches/benches/algorithms/mod.rs | 9 ++ benches/benches/algorithms/mul.rs | 26 ++++ benches/benches/div.rs | 80 ++++++++++ benches/benches/log.rs | 23 +++ benches/benches/mod.rs | 19 +++ benches/benches/modular.rs | 84 ++++++++++ benches/benches/mul.rs | 61 ++++++++ benches/benches/pow.rs | 39 +++++ benches/benches/root.rs | 23 +++ criterion.rs | 7 - src/add.rs | 66 +------- src/algorithms/add.rs | 1 + src/algorithms/div/mod.rs | 19 +-- src/algorithms/div/reciprocal.rs | 47 ------ src/algorithms/div/small.rs | 109 ------------- src/algorithms/gcd/matrix.rs | 75 --------- src/algorithms/gcd/mod.rs | 11 -- src/algorithms/mod.rs | 17 +-- src/algorithms/mul.rs | 38 +---- src/algorithms/ops.rs | 2 + src/algorithms/shift.rs | 2 +- src/base_convert.rs | 2 +- src/bits.rs | 6 +- src/const_for.rs | 10 +- src/div.rs | 96 +----------- src/from.rs | 21 ++- src/lib.rs | 32 ++-- src/log.rs | 35 ----- src/macros.rs | 72 +++++++++ src/modular.rs | 96 ------------ src/mul.rs | 76 +--------- src/pow.rs | 51 ------- src/root.rs | 35 ----- src/support/arbitrary.rs | 2 +- src/support/quickcheck.rs | 2 +- src/support/rand.rs | 2 +- src/support/rlp.rs | 1 + src/utils.rs | 83 +--------- 48 files changed, 870 insertions(+), 974 deletions(-) create mode 100644 benches/bench.rs create mode 100644 benches/benches/add.rs create mode 100644 benches/benches/algorithms/div/mod.rs create mode 100644 benches/benches/algorithms/div/reciprocal.rs create mode 100644 benches/benches/algorithms/div/small.rs create mode 100644 benches/benches/algorithms/gcd.rs create mode 100644 benches/benches/algorithms/mod.rs create mode 100644 benches/benches/algorithms/mul.rs create mode 100644 benches/benches/div.rs create mode 100644 benches/benches/log.rs create mode 100644 benches/benches/mod.rs create mode 100644 benches/benches/modular.rs create mode 100644 benches/benches/mul.rs create mode 100644 benches/benches/pow.rs create mode 100644 benches/benches/root.rs delete mode 100644 criterion.rs create mode 100644 src/macros.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index a8f4975..e757e11 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,3 @@ -[alias] -criterion = "bench --bench=criterion --features=bench" - # This enables KaTex in docs, but requires running `cargo doc --no-deps`. [build] rustdocflags = "--html-in-header .cargo/katex-header.html" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3f9ea56..0ce24e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: - name: Build with code coverage run: | cargo llvm-cov --no-report --locked --workspace --all-features --all-targets -- --help - cargo llvm-cov --no-report --locked --workspace --all-features --doc -- --help + cargo llvm-cov --no-report --locked --workspace --all-features --doc - name: Generate code coverage env: # Covered tests are slower, so reduce the test load. (We also shouldn't diff --git a/Cargo.lock b/Cargo.lock index 1ec4cd5..0c8ccc8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,6 +39,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "anstyle" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" + [[package]] name = "approx" version = "0.5.1" @@ -185,7 +191,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -197,17 +203,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "auto_impl" version = "1.0.1" @@ -262,6 +257,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" + [[package]] name = "bitvec" version = "1.0.1" @@ -369,25 +370,29 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.23" +version = "4.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "98330784c494e49850cb23b8e2afcca13587d2500b2e3f1f78ae20248059c9be" dependencies = [ - "bitflags", - "clap_lex", - "indexmap", - "textwrap", + "clap_builder", ] [[package]] -name = "clap_lex" -version = "0.2.4" +name = "clap_builder" +version = "4.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +checksum = "e182eb5f2562a67dda37e2c57af64d720a9e010c5e860ed87c056586aeafa52e" dependencies = [ - "os_str_bytes", + "anstyle", + "clap_lex", ] +[[package]] +name = "clap_lex" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" + [[package]] name = "convert_case" version = "0.4.0" @@ -442,19 +447,19 @@ checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" [[package]] name = "criterion" -version = "0.4.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" +checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f" dependencies = [ "anes", - "atty", "cast", "ciborium", "clap", "criterion-plot", + "is-terminal", "itertools", - "lazy_static", "num-traits", + "once_cell", "oorandom", "plotters", "rayon", @@ -738,7 +743,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -824,15 +829,6 @@ dependencies = [ "hashbrown 0.12.3", ] -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.2.6" @@ -935,6 +931,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.1", + "rustix 0.38.4", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -967,9 +974,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libm" @@ -983,6 +990,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2" +[[package]] +name = "linux-raw-sys" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" + [[package]] name = "lock_api" version = "0.4.9" @@ -1131,7 +1144,7 @@ version = "0.10.50" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e30d8bc91859781f0a943411186324d580f2bbeb71b452fe91ae344806af3f1" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "foreign-types", "libc", @@ -1148,7 +1161,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -1169,12 +1182,6 @@ dependencies = [ "vcpkg", ] -[[package]] -name = "os_str_bytes" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" - [[package]] name = "parity-scale-codec" version = "3.4.0" @@ -1421,9 +1428,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -1435,7 +1442,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -1534,9 +1541,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" dependencies = [ "proc-macro2", ] @@ -1614,7 +1621,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1623,7 +1630,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1720,11 +1727,24 @@ version = "0.37.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "722529a737f5a942fdbac3a46cee213053196737c5eaa3386d52e85b786f2659" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.2", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +dependencies = [ + "bitflags 2.3.3", + "errno", + "libc", + "linux-raw-sys 0.4.3", "windows-sys 0.48.0", ] @@ -1776,7 +1796,7 @@ version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1816,7 +1836,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -1901,7 +1921,7 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ "ahash 0.7.6", "atoi", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "crc", @@ -1980,9 +2000,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" dependencies = [ "proc-macro2", "quote", @@ -2010,16 +2030,10 @@ dependencies = [ "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.12", "windows-sys 0.45.0", ] -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - [[package]] name = "thiserror" version = "1.0.40" @@ -2037,7 +2051,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] [[package]] @@ -2565,5 +2579,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.26", ] diff --git a/Cargo.toml b/Cargo.toml index 293c6aa..3088f7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,28 +16,25 @@ members = ["ruint-macro"] [features] default = [] -bench = ["dep:criterion", "proptest", "rand"] dyn = ["dep:smallvec"] generic_const_exprs = [] postgres = ["dep:postgres-types", "dep:bytes"] sqlx = ["dep:sqlx-core"] [[bench]] -name = "criterion" +name = "bench_uint" harness = false -path = "criterion.rs" -required-features = ["bench"] +path = "benches/bench.rs" [dependencies] arbitrary = { version = "1.1", optional = true } ark-ff = { version = "0.4.0", optional = true } bn-rs = { version = "0.2", optional = true } bytes = { version = "1.1", optional = true } -criterion = { version = "0.4", optional = true } # Secretly dev-dependencies derive_more = "0.99.17" fastrlp = { version = "0.3.1", optional = true } num-bigint = { version = "0.4.3", optional = true } -parity-scale-codec = { version = "3.2.1", optional = true, features = [ "max-encoded-len" ] } +parity-scale-codec = { version = "3.2.1", optional = true, features = ["max-encoded-len"] } postgres-types = { version = "0.2.3", optional = true } primitive-types = { version = "<1", optional = true } proptest = { version = "1.0", optional = true } @@ -47,10 +44,10 @@ rand = { version = "0.8.5", optional = true } rlp = { version = "0.5.1", optional = true } ruint-macro = { version = "1.0.2", path = "./ruint-macro" } serde = { version = "1.0", optional = true } -smallvec = { version = "1.8.0", optional = true, features = [ "union" ] } # for UintDyn +smallvec = { version = "1.8.0", optional = true, features = ["union"] } # for UintDyn # HACK: (BLOCKED) sqlx requires a runtime to be specified. # -sqlx-core = { version = "0.6", optional = true, features = [ "runtime-tokio-native-tls" ] } +sqlx-core = { version = "0.6", optional = true, features = ["runtime-tokio-native-tls"] } thiserror = "1.0" valuable = { version = "0.1.0", optional = true } zeroize = { version = "1.5", optional = true } @@ -65,6 +62,9 @@ rustc_version = "0.4.0" [dev-dependencies] ruint = { path = ".", features = ["arbitrary", "proptest"] } +criterion = "0.5" +rand = "0.8" + approx = "0.5.1" ark-bn254 = "0.4.0" bincode = "1.3" @@ -75,16 +75,6 @@ postgres = "0.19.3" proptest = { version = "1.0" } serde_json = "1.0" -# Compilation profile for any non-workspace member. -# Dependencies are optimized, even in a dev build. This improves dev performance -# while having negligible impact on incremental build times. -[profile.dev.package."*"] -opt-level = 3 - -# Produce debug info for release builds -[profile.release] -debug = true - [package.metadata.docs.rs] rustdoc-args = ["--cfg", "has_cfg_doc", "--html-in-header", ".cargo/katex-header.html"] all-features = true diff --git a/benches/bench.rs b/benches/bench.rs new file mode 100644 index 0000000..a11ebdd --- /dev/null +++ b/benches/bench.rs @@ -0,0 +1,19 @@ +mod benches; + +mod prelude { + pub use criterion::{BatchSize, Criterion}; + pub use proptest::{ + arbitrary::Arbitrary, + strategy::{Strategy, ValueTree}, + test_runner::TestRunner, + }; + pub use rand::prelude::*; + pub use ruint::{const_for, nlimbs, uint, Bits, Uint, UintTryFrom, UintTryTo}; + pub use std::hint::black_box; +} + +fn main() { + let mut c = criterion::Criterion::default().configure_from_args(); + benches::group(&mut c); + c.final_summary(); +} diff --git a/benches/benches/add.rs b/benches/benches/add.rs new file mode 100644 index 0000000..28ee251 --- /dev/null +++ b/benches/benches/add.rs @@ -0,0 +1,46 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_neg::(criterion); + bench_add::(criterion); + bench_sub::(criterion); + }); +} + +fn bench_neg(criterion: &mut Criterion) { + let input = Uint::::arbitrary(); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("neg/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |a| black_box(-black_box(a)), + BatchSize::SmallInput, + ); + }); +} + +fn bench_add(criterion: &mut Criterion) { + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("add/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b)| black_box(black_box(a) + black_box(b)), + BatchSize::SmallInput, + ); + }); +} + +fn bench_sub(criterion: &mut Criterion) { + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("sub/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b)| black_box(black_box(a) - black_box(b)), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/algorithms/div/mod.rs b/benches/benches/algorithms/div/mod.rs new file mode 100644 index 0000000..0f9f32c --- /dev/null +++ b/benches/benches/algorithms/div/mod.rs @@ -0,0 +1,7 @@ +mod reciprocal; +mod small; + +pub fn group(criterion: &mut criterion::Criterion) { + reciprocal::group(criterion); + small::group(criterion); +} diff --git a/benches/benches/algorithms/div/reciprocal.rs b/benches/benches/algorithms/div/reciprocal.rs new file mode 100644 index 0000000..67a1594 --- /dev/null +++ b/benches/benches/algorithms/div/reciprocal.rs @@ -0,0 +1,41 @@ +use crate::prelude::*; +use ruint::algorithms::div::*; + +pub fn group(criterion: &mut Criterion) { + bench_reciprocal_ref(criterion); + bench_reciprocal_mg10(criterion); + bench_reciprocal_2_mg10(criterion); +} + +fn bench_reciprocal_ref(criterion: &mut Criterion) { + let mut rng = rand::thread_rng(); + criterion.bench_function("algo/div/reciprocal/ref", move |bencher| { + bencher.iter_batched( + || rng.gen::() | (1 << 63), + |a| black_box(reciprocal_ref(black_box(a))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_reciprocal_mg10(criterion: &mut Criterion) { + let mut rng = rand::thread_rng(); + criterion.bench_function("algo/div/reciprocal/mg10", move |bencher| { + bencher.iter_batched( + || rng.gen::() | (1 << 63), + |a| black_box(reciprocal_mg10(black_box(a))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_reciprocal_2_mg10(criterion: &mut Criterion) { + let mut rng = rand::thread_rng(); + criterion.bench_function("algo/div/reciprocal_2/mg10", move |bencher| { + bencher.iter_batched( + || rng.gen::() | (1 << 127), + |a| black_box(reciprocal_2_mg10(black_box(a))), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/algorithms/div/small.rs b/benches/benches/algorithms/div/small.rs new file mode 100644 index 0000000..5023354 --- /dev/null +++ b/benches/benches/algorithms/div/small.rs @@ -0,0 +1,103 @@ +use crate::prelude::*; +use ruint::algorithms::div::*; + +pub fn group(criterion: &mut Criterion) { + bench_div_2x1_ref(criterion); + bench_div_2x1_mg10(criterion); + bench_div_3x2_ref(criterion); + bench_div_3x2_mg10(criterion); +} + +fn bench_div_2x1_ref(criterion: &mut Criterion) { + let mut rng = thread_rng(); + criterion.bench_function("algo/div/2x1/ref", move |bencher| { + bencher.iter_batched( + || { + let q: u64 = rng.gen(); + let r: u64 = rng.gen(); + let d = rng.gen::() | (1 << 63); + let r = r % d; + let n = u128::from(q) * u128::from(d) + u128::from(r); + (n, d) + }, + |(u, d)| black_box(div_2x1_ref(u, d)), + BatchSize::SmallInput, + ); + }); +} + +fn bench_div_2x1_mg10(criterion: &mut Criterion) { + let mut rng = thread_rng(); + criterion.bench_function("algo/div/2x1/mg10", move |bencher| { + bencher.iter_batched( + || { + let q: u64 = rng.gen(); + let r: u64 = rng.gen(); + let d = rng.gen::() | (1 << 63); + let r = r % d; + let n = u128::from(q) * u128::from(d) + u128::from(r); + let v = reciprocal(d); + (n, d, v) + }, + |(u, d, v)| black_box(div_2x1_mg10(u, d, v)), + BatchSize::SmallInput, + ); + }); +} + +fn bench_div_3x2_ref(criterion: &mut Criterion) { + let mut rng = thread_rng(); + criterion.bench_function("algo/div/3x2/ref", move |bencher| { + bencher.iter_batched( + || { + let q: u64 = rng.gen(); + let r: u128 = rng.gen(); + let d = rng.gen::() | (1 << 127); + let r = r % d; + let (n21, n0) = { + let d1 = (d >> 64) as u64; + let d0 = d as u64; + let r1 = (r >> 64) as u64; + let r0 = r as u64; + // n = q * d + r + let n10 = u128::from(q) * u128::from(d0) + u128::from(r0); + let n0 = n10 as u64; + let n21 = (n10 >> 64) + u128::from(q) * u128::from(d1) + u128::from(r1); + (n21, n0) + }; + (n21, n0, d) + }, + |(n21, n0, d)| black_box(div_3x2_ref(n21, n0, d)), + BatchSize::SmallInput, + ); + }); +} + +fn bench_div_3x2_mg10(criterion: &mut Criterion) { + let mut rng = thread_rng(); + criterion.bench_function("algo/div/3x2/mg10", move |bencher| { + bencher.iter_batched( + || { + let q: u64 = rng.gen(); + let r: u128 = rng.gen(); + let d = rng.gen::() | (1 << 127); + let r = r % d; + let (n21, n0) = { + let d1 = (d >> 64) as u64; + let d0 = d as u64; + let r1 = (r >> 64) as u64; + let r0 = r as u64; + // n = q * d + r + let n10 = u128::from(q) * u128::from(d0) + u128::from(r0); + let n0 = n10 as u64; + let n21 = (n10 >> 64) + u128::from(q) * u128::from(d1) + u128::from(r1); + (n21, n0) + }; + let v = reciprocal_2(d); + (n21, n0, d, v) + }, + |(n21, n0, d, v)| black_box(div_3x2_mg10(n21, n0, d, v)), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/algorithms/gcd.rs b/benches/benches/algorithms/gcd.rs new file mode 100644 index 0000000..7477831 --- /dev/null +++ b/benches/benches/algorithms/gcd.rs @@ -0,0 +1,65 @@ +use crate::prelude::*; +use ruint::algorithms::LehmerMatrix as Matrix; +use std::cmp::{max, min}; + +pub fn group(criterion: &mut Criterion) { + bench_from_u64(criterion); + bench_from_u64_prefix(criterion); + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_apply::(criterion); + }); +} + +fn bench_from_u64(criterion: &mut Criterion) { + let input = (u64::arbitrary(), u64::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function("algorithms/gcd/matrix/from_u64", move |bencher| { + bencher.iter_batched( + || { + let (a, b) = input.new_tree(&mut runner).unwrap().current(); + (max(a, b), min(a, b)) + }, + |(a, b)| black_box(Matrix::from_u64(black_box(a), black_box(b))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_from_u64_prefix(criterion: &mut Criterion) { + let input = (u64::arbitrary(), u64::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function("algorithms/gcd/matrix/from_u64_prefix", move |bencher| { + bencher.iter_batched( + || { + let (a, b) = input.new_tree(&mut runner).unwrap().current(); + (max(a, b), min(a, b)) + }, + |(a, b)| black_box(Matrix::from_u64_prefix(black_box(a), black_box(b))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_apply(criterion: &mut Criterion) { + let input = ( + Uint::::arbitrary(), + Uint::::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function( + &format!("algorithms/gcd/matrix/apply/{BITS}"), + move |bencher| { + bencher.iter_batched( + || { + let (a, b) = input.new_tree(&mut runner).unwrap().current(); + let (a, b) = (max(a, b), min(a, b)); + let m = Matrix::from(a, b); + (a, b, m) + }, + |(a, b, m)| black_box(m).apply(&mut black_box(a), &mut black_box(b)), + BatchSize::SmallInput, + ); + }, + ); +} diff --git a/benches/benches/algorithms/mod.rs b/benches/benches/algorithms/mod.rs new file mode 100644 index 0000000..b8a67ee --- /dev/null +++ b/benches/benches/algorithms/mod.rs @@ -0,0 +1,9 @@ +mod div; +mod gcd; +mod mul; + +pub fn group(criterion: &mut criterion::Criterion) { + self::mul::group(criterion); + self::div::group(criterion); + self::gcd::group(criterion); +} diff --git a/benches/benches/algorithms/mul.rs b/benches/benches/algorithms/mul.rs new file mode 100644 index 0000000..1352a18 --- /dev/null +++ b/benches/benches/algorithms/mul.rs @@ -0,0 +1,26 @@ +use crate::prelude::*; +use ruint::algorithms::addmul_n; + +pub fn group(criterion: &mut Criterion) { + bench_addmul_nnn(criterion); +} + +fn bench_addmul_nnn(criterion: &mut Criterion) { + const_for!(SIZE in [0,1,2,3,4,5,6] { + let mut rng = rand::thread_rng(); + criterion.bench_function(&format!("algo/addmul_n/{SIZE}"), move |bencher| { + bencher.iter_batched( + || ( + rng.gen::<[u64; SIZE]>(), + rng.gen::<[u64; SIZE]>(), + rng.gen::<[u64; SIZE]>(), + ), + |(mut lhs, a, b)| { + addmul_n(&mut lhs, &a, &b); + black_box(lhs) + }, + BatchSize::SmallInput, + ); + }); + }); +} diff --git a/benches/benches/div.rs b/benches/benches/div.rs new file mode 100644 index 0000000..f8c0bd0 --- /dev/null +++ b/benches/benches/div.rs @@ -0,0 +1,80 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_div_rem_small::(criterion); + bench_div_rem_half::(criterion); + bench_div_rem_full::(criterion); + }); +} + +fn bench_div_rem_small(criterion: &mut Criterion) { + if BITS == 0 { + return; + } + let input = (Uint::::arbitrary(), u64::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("div_rem/{BITS}/64"), move |bencher| { + bencher.iter_batched( + || { + let (n, mut d) = input.new_tree(&mut runner).unwrap().current(); + if BITS < 64 { + d &= Uint::::MASK; + } + if d == 0 { + d = 1; + } + (n, Uint::from(d)) + }, + |(a, b)| black_box(black_box(a).div_rem(black_box(b))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_div_rem_half(criterion: &mut Criterion) { + if BITS == 0 { + return; + } + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function( + &format!("div_rem/{BITS}/{}", BITS - BITS / 2), + move |bencher| { + bencher.iter_batched( + || { + let (n, mut d) = input.new_tree(&mut runner).unwrap().current(); + d >>= BITS / 2; // make d half size + if d == Uint::ZERO { + d = Uint::from(1); + } + (n, d) + }, + |(a, b)| black_box(black_box(a).div_rem(black_box(b))), + BatchSize::SmallInput, + ); + }, + ); +} + +fn bench_div_rem_full(criterion: &mut Criterion) { + if BITS == 0 { + return; + } + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("div_rem/{BITS}/{BITS}"), move |bencher| { + bencher.iter_batched( + || { + let (n, mut d) = input.new_tree(&mut runner).unwrap().current(); + if d == Uint::ZERO { + d = Uint::from(1); + } + (n, d) + }, + |(a, b)| black_box(black_box(a).div_rem(black_box(b))), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/log.rs b/benches/benches/log.rs new file mode 100644 index 0000000..5434cc8 --- /dev/null +++ b/benches/benches/log.rs @@ -0,0 +1,23 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_log::(criterion); + }); +} + +fn bench_log(criterion: &mut Criterion) { + if BITS < 7 { + return; + } + let input = (Uint::::arbitrary(), 2_u64..100); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("log/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(n, b)| black_box(black_box(n).checked_log(Uint::::from(b))), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/mod.rs b/benches/benches/mod.rs new file mode 100644 index 0000000..e66125d --- /dev/null +++ b/benches/benches/mod.rs @@ -0,0 +1,19 @@ +mod add; +mod algorithms; +mod div; +mod log; +mod modular; +mod mul; +mod pow; +mod root; + +pub fn group(c: &mut criterion::Criterion) { + add::group(c); + mul::group(c); + div::group(c); + pow::group(c); + log::group(c); + root::group(c); + modular::group(c); + algorithms::group(c); +} diff --git a/benches/benches/modular.rs b/benches/benches/modular.rs new file mode 100644 index 0000000..0af2fb0 --- /dev/null +++ b/benches/benches/modular.rs @@ -0,0 +1,84 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_reduce::(criterion); + bench_add::(criterion); + bench_mul::(criterion); + bench_pow::(criterion); + bench_inv::(criterion); + }); +} + +fn bench_reduce(criterion: &mut Criterion) { + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("reduce_mod/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, m)| black_box(black_box(a).reduce_mod(black_box(m))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_add(criterion: &mut Criterion) { + let input = ( + Uint::::arbitrary(), + Uint::arbitrary(), + Uint::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("add_mod/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b, m)| black_box(black_box(a).add_mod(black_box(b), black_box(m))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_mul(criterion: &mut Criterion) { + let input = ( + Uint::::arbitrary(), + Uint::arbitrary(), + Uint::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("mul_mod/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b, m)| black_box(black_box(a).mul_mod(black_box(b), black_box(m))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_pow(criterion: &mut Criterion) { + let input = ( + Uint::::arbitrary(), + Uint::arbitrary(), + Uint::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("pow_mod/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b, m)| black_box(black_box(a).pow_mod(black_box(b), black_box(m))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_inv(criterion: &mut Criterion) { + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("inv_mod/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, m)| black_box(black_box(a).inv_mod(black_box(m))), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/mul.rs b/benches/benches/mul.rs new file mode 100644 index 0000000..e9c3e0a --- /dev/null +++ b/benches/benches/mul.rs @@ -0,0 +1,61 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_mul::(criterion); + }); + const_for!(BITS_LHS in [64, 256,1024] { + const LIMBS_LHS: usize = nlimbs(BITS_LHS); + const_for!(BITS_RHS in [64, 256,1024] { + const LIMBS_RHS: usize = nlimbs(BITS_RHS); + const BITS_RES: usize = BITS_LHS + BITS_RHS; + const LIMBS_RES: usize = nlimbs(BITS_RES); + bench_widening_mul::(criterion); + }); + }); +} + +fn bench_mul(criterion: &mut Criterion) { + let input = (Uint::::arbitrary(), Uint::arbitrary()); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("mul/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b)| black_box(black_box(a) * black_box(b)), + BatchSize::SmallInput, + ); + }); +} + +fn bench_widening_mul< + const BITS_LHS: usize, + const LIMBS_LHS: usize, + const BITS_RHS: usize, + const LIMBS_RHS: usize, + const BITS_RES: usize, + const LIMBS_RES: usize, +>( + criterion: &mut Criterion, +) { + let input = ( + Uint::::arbitrary(), + Uint::::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function( + &format!("widening_mul/{BITS_LHS}/{BITS_RHS}"), + move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(a, b)| { + black_box( + black_box(a) + .widening_mul::(black_box(b)), + ) + }, + BatchSize::SmallInput, + ); + }, + ); +} diff --git a/benches/benches/pow.rs b/benches/benches/pow.rs new file mode 100644 index 0000000..76521c9 --- /dev/null +++ b/benches/benches/pow.rs @@ -0,0 +1,39 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_pow::(criterion); + bench_overflowing_pow::(criterion); + }); +} + +fn bench_pow(criterion: &mut Criterion) { + let input = ( + Uint::::arbitrary(), + Uint::::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("pow/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(b, e)| black_box(black_box(b).pow(black_box(e))), + BatchSize::SmallInput, + ); + }); +} + +fn bench_overflowing_pow(criterion: &mut Criterion) { + let input = ( + Uint::::arbitrary(), + Uint::::arbitrary(), + ); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("overflowing_pow/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |(b, e)| black_box(black_box(b).overflowing_pow(black_box(e))), + BatchSize::SmallInput, + ); + }); +} diff --git a/benches/benches/root.rs b/benches/benches/root.rs new file mode 100644 index 0000000..7453b38 --- /dev/null +++ b/benches/benches/root.rs @@ -0,0 +1,23 @@ +use crate::prelude::*; + +pub fn group(criterion: &mut Criterion) { + const_for!(BITS in BENCH { + const LIMBS: usize = nlimbs(BITS); + bench_root::(criterion, 2); + bench_root::(criterion, 3); + bench_root::(criterion, 5); + bench_root::(criterion, 127); + }); +} + +fn bench_root(criterion: &mut Criterion, degree: usize) { + let input = Uint::::arbitrary(); + let mut runner = TestRunner::deterministic(); + criterion.bench_function(&format!("root/{degree}/{BITS}"), move |bencher| { + bencher.iter_batched( + || input.new_tree(&mut runner).unwrap().current(), + |value| black_box(black_box(value).root(black_box(degree))), + BatchSize::SmallInput, + ); + }); +} diff --git a/criterion.rs b/criterion.rs deleted file mode 100644 index 017ff92..0000000 --- a/criterion.rs +++ /dev/null @@ -1,7 +0,0 @@ -use ruint as lib; - -fn main() { - let mut criterion = criterion::Criterion::default().configure_from_args(); - lib::bench::group(&mut criterion); - criterion.final_summary(); -} diff --git a/src/add.rs b/src/add.rs index a0bd65a..d316db1 100644 --- a/src/add.rs +++ b/src/add.rs @@ -1,4 +1,4 @@ -use crate::{impl_bin_op, Uint}; +use crate::Uint; use core::{ iter::Sum, ops::{Add, AddAssign, Neg, Sub, SubAssign}, @@ -65,7 +65,7 @@ impl Uint { } let mut carry = 0_u128; #[allow(clippy::cast_possible_truncation)] // Intentional - for (lhs, rhs) in self.limbs.iter_mut().zip(rhs.limbs.into_iter()) { + for (lhs, rhs) in self.limbs.iter_mut().zip(rhs.limbs) { carry += u128::from(*lhs) + u128::from(rhs); *lhs = carry as u64; carry >>= 64; @@ -102,7 +102,7 @@ impl Uint { let mut carry = 0_i128; #[allow(clippy::cast_possible_truncation)] // Intentional #[allow(clippy::cast_sign_loss)] // Intentional - for (lhs, rhs) in self.limbs.iter_mut().zip(rhs.limbs.into_iter()) { + for (lhs, rhs) in self.limbs.iter_mut().zip(rhs.limbs) { carry += i128::from(*lhs) - i128::from(rhs); *lhs = carry as u64; carry >>= 64; // Sign extending shift @@ -203,7 +203,7 @@ impl_bin_op!(Add, add, AddAssign, add_assign, wrapping_add); impl_bin_op!(Sub, sub, SubAssign, sub_assign, wrapping_sub); #[cfg(test)] -pub mod tests { +mod tests { use super::*; use crate::{const_for, nlimbs}; use proptest::proptest; @@ -265,61 +265,3 @@ pub mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_neg::(criterion); - bench_add::(criterion); - bench_sub::(criterion); - }); - } - - fn bench_neg(criterion: &mut Criterion) { - let input = Uint::::arbitrary(); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("neg/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |a| black_box(-black_box(a)), - BatchSize::SmallInput, - ); - }); - } - - fn bench_add(criterion: &mut Criterion) { - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("add/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b)| black_box(black_box(a) + black_box(b)), - BatchSize::SmallInput, - ); - }); - } - - fn bench_sub(criterion: &mut Criterion) { - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("sub/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b)| black_box(black_box(a) - black_box(b)), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/algorithms/add.rs b/src/algorithms/add.rs index e3bd126..74cbb57 100644 --- a/src/algorithms/add.rs +++ b/src/algorithms/add.rs @@ -4,6 +4,7 @@ use super::ops::{adc, sbb}; use core::cmp::Ordering; #[inline(always)] +#[must_use] pub fn cmp(lhs: &[u64], rhs: &[u64]) -> Ordering { debug_assert_eq!(lhs.len(), rhs.len()); for (l, r) in lhs.iter().rev().zip(rhs.iter().rev()) { diff --git a/src/algorithms/div/mod.rs b/src/algorithms/div/mod.rs index 6db99bb..909b199 100644 --- a/src/algorithms/div/mod.rs +++ b/src/algorithms/div/mod.rs @@ -20,8 +20,11 @@ mod small; pub use self::{ knuth::{div_nxm, div_nxm_normalized}, - reciprocal::{reciprocal, reciprocal_2}, - small::{div_2x1, div_3x2, div_nx1, div_nx1_normalized, div_nx2, div_nx2_normalized}, + reciprocal::{reciprocal, reciprocal_2, reciprocal_2_mg10, reciprocal_mg10, reciprocal_ref}, + small::{ + div_2x1, div_2x1_mg10, div_2x1_ref, div_3x2, div_3x2_mg10, div_3x2_ref, div_nx1, + div_nx1_normalized, div_nx2, div_nx2_normalized, + }, }; use crate::algorithms::DoubleWord; @@ -456,15 +459,3 @@ mod tests { assert_eq!(divisor, expected_remainder); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use criterion::Criterion; - - pub fn group(criterion: &mut Criterion) { - reciprocal::bench::group(criterion); - small::bench::group(criterion); - } -} diff --git a/src/algorithms/div/reciprocal.rs b/src/algorithms/div/reciprocal.rs index e84e749..3a1cd25 100644 --- a/src/algorithms/div/reciprocal.rs +++ b/src/algorithms/div/reciprocal.rs @@ -188,50 +188,3 @@ mod tests { ); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use criterion::{black_box, BatchSize, Criterion}; - use rand::Rng; - - pub fn group(criterion: &mut Criterion) { - bench_reciprocal_ref(criterion); - bench_reciprocal_mg10(criterion); - bench_reciprocal_2_mg10(criterion); - } - - fn bench_reciprocal_ref(criterion: &mut Criterion) { - let mut rng = rand::thread_rng(); - criterion.bench_function("algo/div/reciprocal/ref", move |bencher| { - bencher.iter_batched( - || rng.gen::() | (1 << 63), - |a| black_box(reciprocal_ref(black_box(a))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_reciprocal_mg10(criterion: &mut Criterion) { - let mut rng = rand::thread_rng(); - criterion.bench_function("algo/div/reciprocal/mg10", move |bencher| { - bencher.iter_batched( - || rng.gen::() | (1 << 63), - |a| black_box(reciprocal_mg10(black_box(a))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_reciprocal_2_mg10(criterion: &mut Criterion) { - let mut rng = rand::thread_rng(); - criterion.bench_function("algo/div/reciprocal_2/mg10", move |bencher| { - bencher.iter_batched( - || rng.gen::() | (1 << 127), - |a| black_box(reciprocal_2_mg10(black_box(a))), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/algorithms/div/small.rs b/src/algorithms/div/small.rs index 00d1918..719eecb 100644 --- a/src/algorithms/div/small.rs +++ b/src/algorithms/div/small.rs @@ -423,112 +423,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use criterion::{black_box, BatchSize, Criterion}; - use rand::{thread_rng, Rng}; - - pub fn group(criterion: &mut Criterion) { - bench_div_2x1_ref(criterion); - bench_div_2x1_mg10(criterion); - bench_div_3x2_ref(criterion); - bench_div_3x2_mg10(criterion); - } - - fn bench_div_2x1_ref(criterion: &mut Criterion) { - let mut rng = thread_rng(); - criterion.bench_function("algo/div/2x1/ref", move |bencher| { - bencher.iter_batched( - || { - let q: u64 = rng.gen(); - let r: u64 = rng.gen(); - let d = rng.gen::() | (1 << 63); - let r = r % d; - let n = u128::from(q) * u128::from(d) + u128::from(r); - (n, d) - }, - |(u, d)| black_box(div_2x1_ref(u, d)), - BatchSize::SmallInput, - ); - }); - } - - fn bench_div_2x1_mg10(criterion: &mut Criterion) { - let mut rng = thread_rng(); - criterion.bench_function("algo/div/2x1/mg10", move |bencher| { - bencher.iter_batched( - || { - let q: u64 = rng.gen(); - let r: u64 = rng.gen(); - let d = rng.gen::() | (1 << 63); - let r = r % d; - let n = u128::from(q) * u128::from(d) + u128::from(r); - let v = reciprocal(d); - (n, d, v) - }, - |(u, d, v)| black_box(div_2x1_mg10(u, d, v)), - BatchSize::SmallInput, - ); - }); - } - - fn bench_div_3x2_ref(criterion: &mut Criterion) { - let mut rng = thread_rng(); - criterion.bench_function("algo/div/3x2/ref", move |bencher| { - bencher.iter_batched( - || { - let q: u64 = rng.gen(); - let r: u128 = rng.gen(); - let d = rng.gen::() | (1 << 127); - let r = r % d; - let (n21, n0) = { - let d1 = (d >> 64) as u64; - let d0 = d as u64; - let r1 = (r >> 64) as u64; - let r0 = r as u64; - // n = q * d + r - let n10 = u128::from(q) * u128::from(d0) + u128::from(r0); - let n0 = n10 as u64; - let n21 = (n10 >> 64) + u128::from(q) * u128::from(d1) + u128::from(r1); - (n21, n0) - }; - (n21, n0, d) - }, - |(n21, n0, d)| black_box(div_3x2_ref(n21, n0, d)), - BatchSize::SmallInput, - ); - }); - } - - fn bench_div_3x2_mg10(criterion: &mut Criterion) { - let mut rng = thread_rng(); - criterion.bench_function("algo/div/3x2/mg10", move |bencher| { - bencher.iter_batched( - || { - let q: u64 = rng.gen(); - let r: u128 = rng.gen(); - let d = rng.gen::() | (1 << 127); - let r = r % d; - let (n21, n0) = { - let d1 = (d >> 64) as u64; - let d0 = d as u64; - let r1 = (r >> 64) as u64; - let r0 = r as u64; - // n = q * d + r - let n10 = u128::from(q) * u128::from(d0) + u128::from(r0); - let n0 = n10 as u64; - let n21 = (n10 >> 64) + u128::from(q) * u128::from(d1) + u128::from(r1); - (n21, n0) - }; - let v = reciprocal_2(d); - (n21, n0, d, v) - }, - |(n21, n0, d, v)| black_box(div_3x2_mg10(n21, n0, d, v)), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/algorithms/gcd/matrix.rs b/src/algorithms/gcd/matrix.rs index 1035543..7996ec8 100644 --- a/src/algorithms/gcd/matrix.rs +++ b/src/algorithms/gcd/matrix.rs @@ -447,78 +447,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use core::cmp::{max, min}; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - bench_from_u64(criterion); - bench_from_u64_prefix(criterion); - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_apply::(criterion); - }); - } - - fn bench_from_u64(criterion: &mut Criterion) { - let input = (u64::arbitrary(), u64::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function("algorithms/gcd/matrix/from_u64", move |bencher| { - bencher.iter_batched( - || { - let (a, b) = input.new_tree(&mut runner).unwrap().current(); - (max(a, b), min(a, b)) - }, - |(a, b)| black_box(Matrix::from_u64(black_box(a), black_box(b))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_from_u64_prefix(criterion: &mut Criterion) { - let input = (u64::arbitrary(), u64::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function("algorithms/gcd/matrix/from_u64_prefix", move |bencher| { - bencher.iter_batched( - || { - let (a, b) = input.new_tree(&mut runner).unwrap().current(); - (max(a, b), min(a, b)) - }, - |(a, b)| black_box(Matrix::from_u64_prefix(black_box(a), black_box(b))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_apply(criterion: &mut Criterion) { - let input = ( - Uint::::arbitrary(), - Uint::::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function( - &format!("algorithms/gcd/matrix/apply/{BITS}"), - move |bencher| { - bencher.iter_batched( - || { - let (a, b) = input.new_tree(&mut runner).unwrap().current(); - let (a, b) = (max(a, b), min(a, b)); - let m = Matrix::from(a, b); - (a, b, m) - }, - |(a, b, m)| black_box(m).apply(&mut black_box(a), &mut black_box(b)), - BatchSize::SmallInput, - ); - }, - ); - } -} diff --git a/src/algorithms/gcd/mod.rs b/src/algorithms/gcd/mod.rs index 60f061e..d4edf1c 100644 --- a/src/algorithms/gcd/mod.rs +++ b/src/algorithms/gcd/mod.rs @@ -250,14 +250,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use criterion::Criterion; - - pub fn group(criterion: &mut Criterion) { - matrix::bench::group(criterion); - } -} diff --git a/src/algorithms/mod.rs b/src/algorithms/mod.rs index ca7b0cf..fa47e80 100644 --- a/src/algorithms/mod.rs +++ b/src/algorithms/mod.rs @@ -12,10 +12,12 @@ mod ops; mod shift; pub use self::{ + add::{adc_n, cmp, sbb_n}, div::div, gcd::{gcd, gcd_extended, inv_mod, LehmerMatrix}, - mul::{addmul, addmul_n, addmul_nx1, submul_nx1}, + mul::{add_nx1, addmul, addmul_n, addmul_nx1, addmul_ref, submul_nx1}, mul_redc::mul_redc, + ops::{adc, sbb}, shift::{shift_left_small, shift_right_small}, }; @@ -79,16 +81,3 @@ impl DoubleWord for u128 { (self.low(), self.high()) } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use criterion::Criterion; - - pub fn group(criterion: &mut Criterion) { - mul::bench::group(criterion); - div::bench::group(criterion); - gcd::bench::group(criterion); - } -} diff --git a/src/algorithms/mul.rs b/src/algorithms/mul.rs index c1dfb7b..1d6770e 100644 --- a/src/algorithms/mul.rs +++ b/src/algorithms/mul.rs @@ -99,7 +99,7 @@ pub fn addmul(mut lhs: &mut [u64], mut a: &[u64], mut b: &[u64]) -> bool { // Iterate over limbs of `b` and add partial products to `lhs`. let mut overflow = false; - for &b in b.iter() { + for &b in b { if lhs.len() >= a.len() { let (target, rest) = lhs.split_at_mut(a.len()); let carry = addmul_nx1(target, a, b); @@ -123,7 +123,7 @@ pub fn add_nx1(lhs: &mut [u64], mut a: u64) -> u64 { if a == 0 { return 0; } - for lhs in lhs.iter_mut() { + for lhs in lhs { let sum = u128::add(*lhs, a); *lhs = sum.low(); a = sum.high(); @@ -342,37 +342,3 @@ mod tests { assert_eq!(borrow, 17196576577663999042); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use crate::const_for; - - use super::*; - use criterion::{black_box, BatchSize, Criterion}; - use rand::Rng; - - pub fn group(criterion: &mut Criterion) { - bench_addmul_nnn(criterion); - } - - fn bench_addmul_nnn(criterion: &mut Criterion) { - const_for!(SIZE in [0,1,2,3,4,5,6] { - let mut rng = rand::thread_rng(); - criterion.bench_function(&format!("algo/addmul_n/{SIZE}"), move |bencher| { - bencher.iter_batched( - || ( - rng.gen::<[u64; SIZE]>(), - rng.gen::<[u64; SIZE]>(), - rng.gen::<[u64; SIZE]>(), - ), - |(mut lhs, a, b)| { - addmul_n(&mut lhs, &a, &b); - black_box(lhs) - }, - BatchSize::SmallInput, - ); - }); - }); - } -} diff --git a/src/algorithms/ops.rs b/src/algorithms/ops.rs index 20ac90b..c22e53e 100644 --- a/src/algorithms/ops.rs +++ b/src/algorithms/ops.rs @@ -1,12 +1,14 @@ use super::DoubleWord; #[inline(always)] +#[must_use] pub fn adc(lhs: u64, rhs: u64, carry: u64) -> (u64, u64) { let result = u128::from(lhs) + u128::from(rhs) + u128::from(carry); result.split() } #[inline(always)] +#[must_use] pub fn sbb(lhs: u64, rhs: u64, borrow: u64) -> (u64, u64) { let result = u128::from(lhs) .wrapping_sub(u128::from(rhs)) diff --git a/src/algorithms/shift.rs b/src/algorithms/shift.rs index 7a9803f..ec6832a 100644 --- a/src/algorithms/shift.rs +++ b/src/algorithms/shift.rs @@ -2,7 +2,7 @@ pub fn shift_left_small(limbs: &mut [u64], amount: usize) -> u64 { debug_assert!(amount < 64); let mut overflow = 0; - for limb in limbs.iter_mut() { + for limb in limbs { let value = (*limb << amount) | overflow; overflow = *limb >> (64 - amount); *limb = value; diff --git a/src/base_convert.rs b/src/base_convert.rs index 9bc059f..d86958a 100644 --- a/src/base_convert.rs +++ b/src/base_convert.rs @@ -101,7 +101,7 @@ impl Uint { // OPT: keep track of non-zero limbs and mul the minimum. let mut carry: u128 = u128::from(digit); #[allow(clippy::cast_possible_truncation)] - for limb in result.limbs.iter_mut() { + for limb in &mut result.limbs { carry += u128::from(*limb) * u128::from(base); *limb = carry as u64; carry >>= 64; diff --git a/src/bits.rs b/src/bits.rs index d0c3980..702addf 100644 --- a/src/bits.rs +++ b/src/bits.rs @@ -1,5 +1,4 @@ use crate::Uint; - use core::ops::{ BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, ShlAssign, Shr, ShrAssign, @@ -109,18 +108,21 @@ impl Uint { /// Returns the number of zeros in the binary representation of `self`. #[must_use] + #[inline] pub fn count_zeros(&self) -> usize { BITS - self.count_ones() } /// Length of the number in bits ignoring leading zeros. #[must_use] + #[inline] pub fn bit_len(&self) -> usize { BITS - self.leading_zeros() } /// Length of the number in bytes ignoring leading zeros. #[must_use] + #[inline] pub fn byte_len(&self) -> usize { (self.bit_len() + 7) / 8 } @@ -389,7 +391,7 @@ impl Not for Uint { if BITS == 0 { return Self::ZERO; } - for limb in self.limbs.iter_mut() { + for limb in &mut self.limbs { *limb = u64::not(*limb); } self.limbs[LIMBS - 1] &= Self::MASK; diff --git a/src/const_for.rs b/src/const_for.rs index ccfea32..f157177 100644 --- a/src/const_for.rs +++ b/src/const_for.rs @@ -49,17 +49,17 @@ macro_rules! const_for { })* }; ($C:ident in SIZES $x:block) => { - const_for!($C in [0] $x); - const_for!($C in NON_ZERO $x); + $crate::const_for!($C in [0] $x); + $crate::const_for!($C in NON_ZERO $x); }; ($C:ident in NON_ZERO $x:block) => { - const_for!($C in [1, 2, 63, 64, 65, 127, 128, 129, 256, 384, 512, 4096] $x); + $crate::const_for!($C in [1, 2, 63, 64, 65, 127, 128, 129, 256, 384, 512, 4096] $x); }; ($C:ident in BENCH $x:block) => { - const_for!($C in [0, 64, 128, 192, 256, 384, 512, 4096] $x); + $crate::const_for!($C in [0, 64, 128, 192, 256, 384, 512, 4096] $x); }; ($C:ident in $S:ident if ( $c:expr ) $x:block) => { - const_for!($C in $S { + $crate::const_for!($C in $S { if $c { $x } diff --git a/src/div.rs b/src/div.rs index ff72b91..0de872d 100644 --- a/src/div.rs +++ b/src/div.rs @@ -1,4 +1,4 @@ -use crate::{algorithms, impl_bin_op, Uint}; +use crate::{algorithms, Uint}; use core::ops::{Div, DivAssign, Rem, RemAssign}; impl Uint { @@ -79,7 +79,7 @@ impl_bin_op!(Div, div, DivAssign, div_assign, wrapping_div); impl_bin_op!(Rem, rem, RemAssign, rem_assign, wrapping_rem); #[cfg(test)] -pub mod tests { +mod tests { use super::*; use crate::{const_for, nlimbs}; use proptest::{prop_assume, proptest}; @@ -136,95 +136,3 @@ pub mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_div_rem_small::(criterion); - bench_div_rem_half::(criterion); - bench_div_rem_full::(criterion); - }); - } - - fn bench_div_rem_small(criterion: &mut Criterion) { - if BITS == 0 { - return; - } - let input = (Uint::::arbitrary(), u64::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("div_rem/{BITS}/64"), move |bencher| { - bencher.iter_batched( - || { - let (n, mut d) = input.new_tree(&mut runner).unwrap().current(); - if BITS < 64 { - d &= Uint::::MASK; - } - if d == 0 { - d = 1; - } - (n, Uint::from(d)) - }, - |(a, b)| black_box(black_box(a).div_rem(black_box(b))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_div_rem_half(criterion: &mut Criterion) { - if BITS == 0 { - return; - } - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function( - &format!("div_rem/{BITS}/{}", BITS - BITS / 2), - move |bencher| { - bencher.iter_batched( - || { - let (n, mut d) = input.new_tree(&mut runner).unwrap().current(); - d >>= BITS / 2; // make d half size - if d == Uint::ZERO { - d = Uint::from(1); - } - (n, d) - }, - |(a, b)| black_box(black_box(a).div_rem(black_box(b))), - BatchSize::SmallInput, - ); - }, - ); - } - - fn bench_div_rem_full(criterion: &mut Criterion) { - if BITS == 0 { - return; - } - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("div_rem/{BITS}/{BITS}"), move |bencher| { - bencher.iter_batched( - || { - let (n, mut d) = input.new_tree(&mut runner).unwrap().current(); - if d == Uint::ZERO { - d = Uint::from(1); - } - (n, d) - }, - |(a, b)| black_box(black_box(a).div_rem(black_box(b))), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/from.rs b/src/from.rs index 0768d31..216a8d3 100644 --- a/src/from.rs +++ b/src/from.rs @@ -32,7 +32,7 @@ // } use crate::Uint; -use core::{any::type_name, convert::TryFrom, fmt::Debug}; +use core::{any::type_name, fmt::Debug}; use thiserror::Error; /// Error for [`TryFrom`][TryFrom] for [`Uint`]. @@ -268,6 +268,7 @@ impl UintTryFrom for Uint>, { + #[inline] fn uint_try_from(value: T) -> Result> { Self::try_from(value) } @@ -373,6 +374,7 @@ macro_rules! impl_from_unsigned_int { impl TryFrom<$uint> for Uint { type Error = ToUintError; + #[inline] fn try_from(value: $uint) -> Result { Self::try_from(value as u64) } @@ -393,7 +395,7 @@ macro_rules! impl_from_signed_int { type Error = ToUintError; fn try_from(value: $int) -> Result { - if value < 0 { + if value.is_negative() { Err(match Self::try_from(value as $uint) { Ok(n) | Err(ToUintError::ValueTooLarge(_, n)) => { ToUintError::ValueNegative(BITS, n) @@ -486,6 +488,7 @@ impl TryFrom for Uint { impl TryFrom for Uint { type Error = ToUintError; + #[inline] fn try_from(value: f32) -> Result { #[allow(clippy::cast_lossless)] Self::try_from(value as f64) @@ -501,6 +504,7 @@ macro_rules! to_value_to_ref { impl TryFrom> for $t { type Error = FromUintError; + #[inline] fn try_from(value: Uint) -> Result { Self::try_from(&value) } @@ -531,6 +535,7 @@ macro_rules! to_int { impl TryFrom<&Uint> for $int { type Error = FromUintError; + #[inline] fn try_from(value: &Uint) -> Result { const SIGNED: bool = <$int>::MIN != 0; const CAPACITY: usize = if SIGNED { <$int>::BITS - 1 } else { <$int>::BITS } as usize; @@ -563,11 +568,11 @@ impl TryFrom<&Uint> for i128 if BITS == 0 { return Ok(0); } + let mut result = value.limbs[0] as i128; if BITS <= 64 { - return Ok(value.as_limbs()[0] as i128); + return Ok(result); } - let mut result = value.as_limbs()[0] as i128; - result |= (value.as_limbs()[1] as i128) << 64; + result |= (value.limbs[1] as i128) << 64; if value.bit_len() > 127 { return Err(Self::Error::Overflow(BITS, result, i128::MAX)); } @@ -586,11 +591,11 @@ impl TryFrom<&Uint> for u128 if BITS == 0 { return Ok(0); } + let mut result = value.limbs[0] as u128; if BITS <= 64 { - return Ok(value.as_limbs()[0] as u128); + return Ok(result); } - let mut result: u128 = value.as_limbs()[0] as u128; - result |= (value.as_limbs()[1] as u128) << 64; + result |= (value.limbs[1] as u128) << 64; if value.bit_len() > 128 { return Err(Self::Error::Overflow(BITS, result, u128::MAX)); } diff --git a/src/lib.rs b/src/lib.rs index 9b0ab73..e65102f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,11 +1,14 @@ #![doc = include_str!("../Readme.md")] #![doc(issue_tracker_base_url = "https://github.com/recmo/uint/issues/")] -#![warn(clippy::all, clippy::pedantic, clippy::cargo, clippy::nursery)] +#![warn(clippy::all, clippy::pedantic, clippy::nursery)] #![allow( - clippy::module_name_repetitions, + clippy::doc_markdown, // Unfortunately many false positives on Latex. clippy::inline_always, + clippy::module_name_repetitions, + clippy::module_name_repetitions, + clippy::redundant_pub_crate, clippy::unreadable_literal, - clippy::doc_markdown // Unfortunately many false positives on Latex. + clippy::let_unit_value, )] #![cfg_attr( any(test, feature = "bench"), @@ -30,6 +33,9 @@ // See extern crate self as ruint; +#[macro_use] +mod macros; + mod add; pub mod algorithms; pub mod aliases; @@ -144,7 +150,7 @@ impl Uint { pub const LIMBS: usize = nlimbs(BITS); /// Bit mask for the last limb. - const MASK: u64 = mask(BITS); + pub const MASK: u64 = mask(BITS); /// The size of this integer type in bits. pub const BITS: usize = BITS; @@ -349,21 +355,3 @@ mod test { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use criterion::Criterion; - - pub fn group(criterion: &mut Criterion) { - add::bench::group(criterion); - mul::bench::group(criterion); - div::bench::group(criterion); - pow::bench::group(criterion); - log::bench::group(criterion); - root::bench::group(criterion); - modular::bench::group(criterion); - algorithms::bench::group(criterion); - } -} diff --git a/src/log.rs b/src/log.rs index 11ce8ae..784ab01 100644 --- a/src/log.rs +++ b/src/log.rs @@ -189,38 +189,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_log::(criterion); - }); - } - - fn bench_log(criterion: &mut Criterion) { - if BITS < 7 { - return; - } - let input = (Uint::::arbitrary(), 2_u64..100); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("log/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(n, b)| black_box(black_box(n).checked_log(Uint::::from(b))), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..d00827b --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,72 @@ +macro_rules! impl_bin_op { + ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident, $fdel:ident) => { + impl $trait_assign> + for Uint + { + #[allow(clippy::inline_always)] + #[inline(always)] + #[track_caller] + fn $fn_assign(&mut self, rhs: Uint) { + *self = self.$fdel(rhs); + } + } + impl $trait_assign<&Uint> + for Uint + { + #[allow(clippy::inline_always)] + #[inline(always)] + #[track_caller] + fn $fn_assign(&mut self, rhs: &Uint) { + *self = self.$fdel(*rhs); + } + } + impl $trait> + for Uint + { + type Output = Uint; + + #[allow(clippy::inline_always)] + #[inline(always)] + #[track_caller] + fn $fn(self, rhs: Uint) -> Self::Output { + self.$fdel(rhs) + } + } + impl $trait<&Uint> + for Uint + { + type Output = Uint; + + #[allow(clippy::inline_always)] + #[inline(always)] + #[track_caller] + fn $fn(self, rhs: &Uint) -> Self::Output { + self.$fdel(*rhs) + } + } + impl $trait> + for &Uint + { + type Output = Uint; + + #[allow(clippy::inline_always)] + #[inline(always)] + #[track_caller] + fn $fn(self, rhs: Uint) -> Self::Output { + self.$fdel(rhs) + } + } + impl $trait<&Uint> + for &Uint + { + type Output = Uint; + + #[allow(clippy::inline_always)] + #[inline(always)] + #[track_caller] + fn $fn(self, rhs: &Uint) -> Self::Output { + self.$fdel(*rhs) + } + } + }; +} diff --git a/src/modular.rs b/src/modular.rs index 85f8baa..eea5260 100644 --- a/src/modular.rs +++ b/src/modular.rs @@ -296,99 +296,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_reduce::(criterion); - bench_add::(criterion); - bench_mul::(criterion); - bench_pow::(criterion); - bench_inv::(criterion); - }); - } - - fn bench_reduce(criterion: &mut Criterion) { - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("reduce_mod/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, m)| black_box(black_box(a).reduce_mod(black_box(m))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_add(criterion: &mut Criterion) { - let input = ( - Uint::::arbitrary(), - Uint::arbitrary(), - Uint::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("add_mod/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b, m)| black_box(black_box(a).add_mod(black_box(b), black_box(m))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_mul(criterion: &mut Criterion) { - let input = ( - Uint::::arbitrary(), - Uint::arbitrary(), - Uint::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("mul_mod/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b, m)| black_box(black_box(a).mul_mod(black_box(b), black_box(m))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_pow(criterion: &mut Criterion) { - let input = ( - Uint::::arbitrary(), - Uint::arbitrary(), - Uint::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("pow_mod/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b, m)| black_box(black_box(a).pow_mod(black_box(b), black_box(m))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_inv(criterion: &mut Criterion) { - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("inv_mod/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, m)| black_box(black_box(a).inv_mod(black_box(m))), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/mul.rs b/src/mul.rs index 0d18d8f..f33d206 100644 --- a/src/mul.rs +++ b/src/mul.rs @@ -1,4 +1,4 @@ -use crate::{algorithms, impl_bin_op, nlimbs, Uint}; +use crate::{algorithms, nlimbs, Uint}; use core::{ iter::Product, num::Wrapping, @@ -265,77 +265,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_mul::(criterion); - }); - const_for!(BITS_LHS in [64, 256,1024] { - const LIMBS_LHS: usize = nlimbs(BITS_LHS); - const_for!(BITS_RHS in [64, 256,1024] { - const LIMBS_RHS: usize = nlimbs(BITS_RHS); - const BITS_RES: usize = BITS_LHS + BITS_RHS; - const LIMBS_RES: usize = nlimbs(BITS_RES); - bench_widening_mul::(criterion); - }); - }); - } - - fn bench_mul(criterion: &mut Criterion) { - let input = (Uint::::arbitrary(), Uint::arbitrary()); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("mul/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b)| black_box(black_box(a) * black_box(b)), - BatchSize::SmallInput, - ); - }); - } - - fn bench_widening_mul< - const BITS_LHS: usize, - const LIMBS_LHS: usize, - const BITS_RHS: usize, - const LIMBS_RHS: usize, - const BITS_RES: usize, - const LIMBS_RES: usize, - >( - criterion: &mut Criterion, - ) { - let input = ( - Uint::::arbitrary(), - Uint::::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function( - &format!("widening_mul/{BITS_LHS}/{BITS_RHS}"), - move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(a, b)| { - black_box( - black_box(a).widening_mul::( - black_box(b), - ), - ) - }, - BatchSize::SmallInput, - ); - }, - ); - } -} diff --git a/src/pow.rs b/src/pow.rs index 850a848..62cbb56 100644 --- a/src/pow.rs +++ b/src/pow.rs @@ -193,54 +193,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_pow::(criterion); - bench_overflowing_pow::(criterion); - }); - } - - fn bench_pow(criterion: &mut Criterion) { - let input = ( - Uint::::arbitrary(), - Uint::::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("pow/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(b, e)| black_box(black_box(b).pow(black_box(e))), - BatchSize::SmallInput, - ); - }); - } - - fn bench_overflowing_pow(criterion: &mut Criterion) { - let input = ( - Uint::::arbitrary(), - Uint::::arbitrary(), - ); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("overflowing_pow/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |(b, e)| black_box(black_box(b).overflowing_pow(black_box(e))), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/root.rs b/src/root.rs index 02d08cc..5c0006e 100644 --- a/src/root.rs +++ b/src/root.rs @@ -134,38 +134,3 @@ mod tests { }); } } - -#[cfg(feature = "bench")] -#[doc(hidden)] -pub mod bench { - use super::*; - use crate::{const_for, nlimbs}; - use ::proptest::{ - arbitrary::Arbitrary, - strategy::{Strategy, ValueTree}, - test_runner::TestRunner, - }; - use criterion::{black_box, BatchSize, Criterion}; - - pub fn group(criterion: &mut Criterion) { - const_for!(BITS in BENCH { - const LIMBS: usize = nlimbs(BITS); - bench_root::(criterion, 2); - bench_root::(criterion, 3); - bench_root::(criterion, 5); - bench_root::(criterion, 127); - }); - } - - fn bench_root(criterion: &mut Criterion, degree: usize) { - let input = Uint::::arbitrary(); - let mut runner = TestRunner::deterministic(); - criterion.bench_function(&format!("root/{degree}/{BITS}"), move |bencher| { - bencher.iter_batched( - || input.new_tree(&mut runner).unwrap().current(), - |value| black_box(black_box(value).root(black_box(degree))), - BatchSize::SmallInput, - ); - }); - } -} diff --git a/src/support/arbitrary.rs b/src/support/arbitrary.rs index b71b0be..efc3a8b 100644 --- a/src/support/arbitrary.rs +++ b/src/support/arbitrary.rs @@ -14,7 +14,7 @@ impl<'a, const BITS: usize, const LIMBS: usize> Arbitrary<'a> for Uint) -> Result { let mut limbs = [0; LIMBS]; if let Some((last, rest)) = limbs.split_last_mut() { - for limb in rest.iter_mut() { + for limb in rest { *limb = u64::arbitrary(u)?; } *last = u.int_in_range(0..=Self::MASK)?; diff --git a/src/support/quickcheck.rs b/src/support/quickcheck.rs index 65f7592..be1205f 100644 --- a/src/support/quickcheck.rs +++ b/src/support/quickcheck.rs @@ -9,7 +9,7 @@ impl Arbitrary for Uint { fn arbitrary(g: &mut Gen) -> Self { let mut limbs = [0; LIMBS]; if let Some((last, rest)) = limbs.split_last_mut() { - for limb in rest.iter_mut() { + for limb in rest { *limb = u64::arbitrary(g); } *last = u64::arbitrary(g) & Self::MASK; diff --git a/src/support/rand.rs b/src/support/rand.rs index 3084186..2267e9c 100644 --- a/src/support/rand.rs +++ b/src/support/rand.rs @@ -14,7 +14,7 @@ impl Distribution> for fn sample(&self, rng: &mut R) -> Uint { let mut limbs = [0; LIMBS]; if let Some((last, rest)) = limbs.split_last_mut() { - for limb in rest.iter_mut() { + for limb in rest { *limb = rng.gen(); } *last = Uniform::new_inclusive(0, Uint::::MASK).sample(rng); diff --git a/src/support/rlp.rs b/src/support/rlp.rs index 742e701..2612c12 100644 --- a/src/support/rlp.rs +++ b/src/support/rlp.rs @@ -34,6 +34,7 @@ impl Decodable for Uint { /// See impl Encodable for Bits { fn rlp_append(&self, s: &mut RlpStream) { + #[allow(clippy::collection_is_never_read)] let bytes = self.to_be_bytes_vec(); bytes.rlp_append(s); } diff --git a/src/utils.rs b/src/utils.rs index 1341168..9af450f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,6 @@ /// Like `a % b` but returns `b` instead of `0`. #[must_use] -pub const fn rem_up(a: usize, b: usize) -> usize { +pub(crate) const fn rem_up(a: usize, b: usize) -> usize { let rem = a % b; if rem > 0 { rem @@ -10,14 +10,14 @@ pub const fn rem_up(a: usize, b: usize) -> usize { } #[must_use] -pub fn trim_end_slice<'a, T: PartialEq>(slice: &'a [T], value: &T) -> &'a [T] { +pub(crate) fn trim_end_slice<'a, T: PartialEq>(slice: &'a [T], value: &T) -> &'a [T] { slice .iter() .rposition(|b| b != value) .map_or_else(|| &slice[..0], |len| &slice[..=len]) } -pub fn trim_end_vec(vec: &mut Vec, value: &T) { +pub(crate) fn trim_end_vec(vec: &mut Vec, value: &T) { if let Some(last) = vec.iter().rposition(|b| b != value) { vec.truncate(last + 1); } else { @@ -39,80 +39,3 @@ pub const fn unlikely(b: bool) -> bool { pub const fn likely(b: bool) -> bool { b } - -#[macro_export] -#[doc(hidden)] -// TODO: (BLOCKED) make this macro `pub(crate)` when supported. -// See -macro_rules! impl_bin_op { - ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident, $fdel:ident) => { - impl $trait_assign> - for Uint - { - #[allow(clippy::inline_always)] - #[inline(always)] - #[track_caller] - fn $fn_assign(&mut self, rhs: Uint) { - *self = self.$fdel(rhs); - } - } - impl $trait_assign<&Uint> - for Uint - { - #[allow(clippy::inline_always)] - #[inline(always)] - #[track_caller] - fn $fn_assign(&mut self, rhs: &Uint) { - *self = self.$fdel(*rhs); - } - } - impl $trait> - for Uint - { - type Output = Uint; - - #[allow(clippy::inline_always)] - #[inline(always)] - #[track_caller] - fn $fn(self, rhs: Uint) -> Self::Output { - self.$fdel(rhs) - } - } - impl $trait<&Uint> - for Uint - { - type Output = Uint; - - #[allow(clippy::inline_always)] - #[inline(always)] - #[track_caller] - fn $fn(self, rhs: &Uint) -> Self::Output { - self.$fdel(*rhs) - } - } - impl $trait> - for &Uint - { - type Output = Uint; - - #[allow(clippy::inline_always)] - #[inline(always)] - #[track_caller] - fn $fn(self, rhs: Uint) -> Self::Output { - self.$fdel(rhs) - } - } - impl $trait<&Uint> - for &Uint - { - type Output = Uint; - - #[allow(clippy::inline_always)] - #[inline(always)] - #[track_caller] - fn $fn(self, rhs: &Uint) -> Self::Output { - self.$fdel(*rhs) - } - } - }; -}