Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/uu/factor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,13 @@ fluent = { workspace = true }
name = "factor"
path = "src/main.rs"

[dev-dependencies]
divan = { workspace = true }
uucore = { workspace = true, features = ["benchmark"] }

[lib]
path = "src/factor.rs"

[[bench]]
name = "factor_bench"
harness = false
84 changes: 84 additions & 0 deletions src/uu/factor/benches/factor_bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

use divan::{Bencher, black_box};
use uu_factor::uumain;
use uucore::benchmark::run_util_function;

/// Benchmark one u64 digit
#[divan::bench]
fn factor_single_u64(bencher: Bencher) {
bencher
.with_inputs(|| 1000000_u64)
.bench_values(|single_u64| {
black_box(run_util_function(uumain, &[&single_u64.to_string()]));
});
}

/// Benchmark multiple u64 digits
#[divan::bench]
fn factor_multiple_u64s(bencher: Bencher) {
bencher
.with_inputs(|| (2_u64, 1000000_u64))
.bench_values(|(start_u64, end_u64)| {
for u64_digit in start_u64..=end_u64 {
black_box(run_util_function(uumain, &[&u64_digit.to_string()]));
}
});
}

/// Benchmark one u128 digit
#[divan::bench]
fn factor_single_u128(bencher: Bencher) {
bencher
.with_inputs(|| 18446744073709551616_u128)
.bench_values(|single_u128| {
black_box(run_util_function(uumain, &[&single_u128.to_string()]));
});
}

/// Benchmark multiple u128 digits
#[divan::bench]
fn factor_multiple_u128s(bencher: Bencher) {
bencher
.with_inputs(|| {
// this is a range of 1 million different u128 integers
(18446744073709551616_u128, 18446744073710551616_u128)
})
.bench_values(|(start_u128, end_u128)| {
for u128_digit in start_u128..=end_u128 {
black_box(run_util_function(uumain, &[&u128_digit.to_string()]));
}
});
}

/// Benchmark single > u128::MAX digits
#[divan::bench]
fn factor_single_big_uint(bencher: Bencher) {
// max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455
bencher
.with_inputs(|| "340_282_366_920_938_463_463_374_607_431_768_211_456")
.bench_values(|single_big_uint| {
black_box(run_util_function(uumain, &[single_big_uint]));
});
}

/// Benchmark multiple > u128::MAX digits
#[divan::bench]
fn factor_multiple_big_uint(bencher: Bencher) {
// max u128 value is 340_282_366_920_938_463_463_374_607_431_768_211_455
bencher
.with_inputs(|| (768_211_456_u64, 769_211_456_u64))
.bench_values(|(start_big_uint, end_big_uint)| {
for digit in start_big_uint..=end_big_uint {
let big_uint_str = format!("340282366920938463463374607431768211456{digit}");
black_box(run_util_function(uumain, &[&big_uint_str]));
}
});
}

fn main() {
divan::main();
}
97 changes: 83 additions & 14 deletions src/uu/factor/src/factor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,95 @@ fn print_factors_str(
return Ok(());
};

let (factorization, remaining) = if x > BigUint::from_u32(1).unwrap() {
num_prime::nt_funcs::factors(x.clone(), None)
if x > BigUint::from_u32(1).unwrap() {
Comment thread
asder8215 marked this conversation as resolved.
Outdated
// use num_prime's factorize64 algorithm for u64 integers
if x <= BigUint::from_u64(u64::MAX).unwrap() {
let prime_factors = num_prime::nt_funcs::factorize64(x.clone().to_u64_digits()[0]);
write_result_u64(w, &x, prime_factors, print_exponents)
.map_err_context(|| translate!("factor-error-write-error"))?;
}
// use num_prime's factorize128 algorithm for u128 integers
else if x <= BigUint::from_u128(u128::MAX).unwrap() {
let rx = num_str.trim().parse::<u128>();
let Ok(x) = rx else {
// return Ok(). it's non-fatal and we should try the next number.
show_warning!("{}: {}", num_str.maybe_quote(), rx.unwrap_err());
set_exit_code(1);
return Ok(());
};
let prime_factors = num_prime::nt_funcs::factorize128(x);
write_result_u128(w, &x, prime_factors, print_exponents)
.map_err_context(|| translate!("factor-error-write-error"))?;
}
// use num_prime's fallible factorization for anything greater than u128::MAX
else {
let (prime_factors, remaining) = num_prime::nt_funcs::factors(x.clone(), None);
if let Some(_remaining) = remaining {
return Err(USimpleError::new(
1,
translate!("factor-error-factorization-incomplete"),
));
}
write_result_big_uint(w, &x, prime_factors, print_exponents)
.map_err_context(|| translate!("factor-error-write-error"))?;
}
} else {
(BTreeMap::new(), None)
};

if let Some(_remaining) = remaining {
return Err(USimpleError::new(
1,
translate!("factor-error-factorization-incomplete"),
));
let empty_primes: BTreeMap<BigUint, usize> = BTreeMap::new();
write_result_big_uint(w, &x, empty_primes, print_exponents)
.map_err_context(|| translate!("factor-error-write-error"))?;
}

write_result(w, &x, factorization, print_exponents)
.map_err_context(|| translate!("factor-error-write-error"))?;

Ok(())
}

fn write_result(
/// Writing out the prime factors for u64 integers
fn write_result_u64(
w: &mut io::BufWriter<impl Write>,
x: &BigUint,
factorization: BTreeMap<u64, usize>,
print_exponents: bool,
) -> io::Result<()> {
write!(w, "{x}:")?;
for (factor, n) in factorization {
if print_exponents {
if n > 1 {
write!(w, " {factor}^{n}")?;
} else {
write!(w, " {factor}")?;
}
} else {
w.write_all(format!(" {factor}").repeat(n).as_bytes())?;
}
}
writeln!(w)?;
w.flush()
}

/// Writing out the prime factors for u128 integers
fn write_result_u128(
w: &mut io::BufWriter<impl Write>,
x: &u128,
factorization: BTreeMap<u128, usize>,
print_exponents: bool,
) -> io::Result<()> {
write!(w, "{x}:")?;
for (factor, n) in factorization {
if print_exponents {
if n > 1 {
write!(w, " {factor}^{n}")?;
} else {
write!(w, " {factor}")?;
}
} else {
w.write_all(format!(" {factor}").repeat(n).as_bytes())?;
}
}
writeln!(w)?;
w.flush()
}

/// Writing out the prime factors for BigUint integers
fn write_result_big_uint(
w: &mut io::BufWriter<impl Write>,
x: &BigUint,
factorization: BTreeMap<BigUint, usize>,
Expand Down
Loading