Skip to content

Commit 32c0a7e

Browse files
committed
factor: add benchmark coverage
1 parent 83a5cd9 commit 32c0a7e

1 file changed

Lines changed: 184 additions & 12 deletions

File tree

src/uu/factor/benches/factor_bench.rs

Lines changed: 184 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,195 @@
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
55

6-
// spell-checker:ignore funcs
6+
// spell-checker:ignore funcs semiprimes
77

88
use divan::{Bencher, black_box};
9+
use num_bigint::BigUint;
10+
use num_prime::nt_funcs::{factorize64, factorize128, factors};
11+
use std::collections::BTreeMap;
912
use uu_factor::uumain;
1013
use uucore::benchmark::run_util_function;
1114

12-
/// Benchmark multiple u64 digits
13-
#[divan::bench(args = [(2)])]
14-
fn factor_multiple_u64s(bencher: Bencher, start_num: u64) {
15-
bencher
16-
// this is a range of 5000 different u128 integers
17-
.with_inputs(|| (start_num, start_num + 2500))
18-
.bench_values(|(start_u64, end_u64)| {
19-
for u64_digit in start_u64..=end_u64 {
20-
black_box(run_util_function(uumain, &[&u64_digit.to_string()]));
21-
}
22-
});
15+
// Internal algorithm benchmarks avoid CLI parsing and stdout overhead.
16+
17+
fn factorize(n: &BigUint) -> (BTreeMap<BigUint, usize>, Option<Vec<BigUint>>) {
18+
match n.bits() {
19+
0..=64 => {
20+
let n_u64 = n
21+
.try_into()
22+
.expect("value with at most 64 bits fits in u64");
23+
let factors = factorize64(n_u64)
24+
.into_iter()
25+
.map(|(factor, count)| (BigUint::from(factor), count))
26+
.collect();
27+
(factors, None)
28+
}
29+
65..=128 => {
30+
let n_u128 = n
31+
.try_into()
32+
.expect("value with at most 128 bits fits in u128");
33+
let factors = factorize128(n_u128)
34+
.into_iter()
35+
.map(|(factor, count)| (BigUint::from(factor), count))
36+
.collect();
37+
(factors, None)
38+
}
39+
_ => factors(n.clone(), None),
40+
}
41+
}
42+
43+
#[divan::bench]
44+
fn factorize_small_u64(bencher: Bencher) {
45+
bencher.bench(|| {
46+
for n in 2u64..=100 {
47+
black_box(factorize(&BigUint::from(n)));
48+
}
49+
});
50+
}
51+
52+
#[divan::bench]
53+
fn factorize_32bit_semiprime(bencher: Bencher) {
54+
let n = BigUint::from(4295098369u64);
55+
56+
bencher.bench(|| {
57+
black_box(factorize(&n));
58+
});
59+
}
60+
61+
#[divan::bench]
62+
fn factorize_64bit_semiprime(bencher: Bencher) {
63+
let n = BigUint::from(18446743979220271189u64);
64+
65+
bencher.bench(|| {
66+
black_box(factorize(&n));
67+
});
68+
}
69+
70+
#[divan::bench]
71+
fn factorize_large_prime(bencher: Bencher) {
72+
let n = BigUint::from(18446744073709551557u64);
73+
74+
bencher.bench(|| {
75+
black_box(factorize(&n));
76+
});
77+
}
78+
79+
#[divan::bench]
80+
fn factorize_close_factors(bencher: Bencher) {
81+
let n = BigUint::from(4294049777u64);
82+
83+
bencher.bench(|| {
84+
black_box(factorize(&n));
85+
});
86+
}
87+
88+
#[divan::bench]
89+
fn factorize_96bit_composite(bencher: Bencher) {
90+
let n = BigUint::parse_bytes(b"19807040619342712411247977", 10).unwrap();
91+
92+
bencher.bench(|| {
93+
black_box(factorize(&n));
94+
});
95+
}
96+
97+
#[divan::bench]
98+
fn factorize_120bit_mixed(bencher: Bencher) {
99+
let n = BigUint::parse_bytes(b"1329227995784915872903807060280344217", 10).unwrap();
100+
101+
bencher.bench(|| {
102+
black_box(factorize(&n));
103+
});
104+
}
105+
106+
// End-to-end benchmarks include CLI parsing and output formatting.
107+
108+
/// Benchmark small u64 numbers via CLI.
109+
#[divan::bench(args = [(2, 502)])]
110+
fn factor_small_u64(bencher: Bencher, (start, end): (u64, u64)) {
111+
bencher.bench(|| {
112+
for n in start..=end {
113+
black_box(run_util_function(uumain, &[&n.to_string()]));
114+
}
115+
});
116+
}
117+
118+
/// Benchmark a longer sequential u64 workload.
119+
#[divan::bench(args = [(2, 2502)])]
120+
fn factor_multiple_u64s(bencher: Bencher, (start, end): (u64, u64)) {
121+
bencher.bench(|| {
122+
for n in start..=end {
123+
black_box(run_util_function(uumain, &[&n.to_string()]));
124+
}
125+
});
126+
}
127+
128+
/// Benchmark medium u64 values including 32-bit semiprimes.
129+
#[divan::bench(args = ["4295098369", "3215031751", "2147483647"])]
130+
fn factor_medium_u64(bencher: Bencher, number: &str) {
131+
bencher.bench(|| {
132+
black_box(run_util_function(uumain, &[number]));
133+
});
134+
}
135+
136+
/// Benchmark large u64 primes.
137+
#[divan::bench(args = ["18446744073709551557", "9223372036854775783"])]
138+
fn factor_large_u64_prime(bencher: Bencher, number: &str) {
139+
bencher.bench(|| {
140+
black_box(run_util_function(uumain, &[number]));
141+
});
142+
}
143+
144+
/// Benchmark the PR timing cases as end-to-end utility runs.
145+
#[divan::bench(args = [
146+
"18446744073709551557", // 64-bit prime near 2^64
147+
"9999999999999999999", // large u64 composite
148+
"123456789012345678901234567890", // 97-bit u128 composite
149+
"18446743979220271189", // 64-bit semiprime
150+
])]
151+
fn factor_pr_timing_cases(bencher: Bencher, number: &str) {
152+
bencher.bench(|| {
153+
black_box(run_util_function(uumain, &[number]));
154+
});
155+
}
156+
157+
/// Benchmark a 64-bit semiprime made from two 32-bit primes.
158+
#[divan::bench]
159+
fn factor_64bit_semiprime(bencher: Bencher) {
160+
bencher.bench(|| {
161+
black_box(run_util_function(uumain, &["18446743979220271189"]));
162+
});
163+
}
164+
165+
/// Benchmark a 96-bit composite.
166+
#[divan::bench]
167+
fn factor_96bit_composite(bencher: Bencher) {
168+
let n = "19807040619342712411247977";
169+
170+
bencher.bench(|| {
171+
black_box(run_util_function(uumain, &[n]));
172+
});
173+
}
174+
175+
/// Benchmark a 120-bit composite with mixed factor sizes.
176+
#[divan::bench]
177+
fn factor_120bit_mixed(bencher: Bencher) {
178+
let n = "1329227995784915872903807060280344217";
179+
180+
bencher.bench(|| {
181+
black_box(run_util_function(uumain, &[n]));
182+
});
183+
}
184+
185+
/// Benchmark multiple numbers in sequence.
186+
#[divan::bench]
187+
fn factor_batch_mixed(bencher: Bencher) {
188+
let test_numbers = ["2", "1000000007", "4295098369", "18446743979220271189"];
189+
190+
bencher.bench(|| {
191+
for n in test_numbers {
192+
black_box(run_util_function(uumain, &[n]));
193+
}
194+
});
23195
}
24196

25197
fn main() {

0 commit comments

Comments
 (0)