mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-04 23:17:46 +00:00
factor: Avoid moving data around in main factoring loop
Instead, the same `Factors` object is passed around through the execution. ~10% faster.
This commit is contained in:
parent
6713d2ad62
commit
2d2b6faab4
2 changed files with 13 additions and 25 deletions
|
@ -9,7 +9,6 @@ extern crate rand;
|
||||||
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::ops;
|
|
||||||
|
|
||||||
use crate::numeric::{Arithmetic, Montgomery};
|
use crate::numeric::{Arithmetic, Montgomery};
|
||||||
use crate::{miller_rabin, rho, table};
|
use crate::{miller_rabin, rho, table};
|
||||||
|
@ -48,14 +47,6 @@ impl Factors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::MulAssign<Factors> for Factors {
|
|
||||||
fn mul_assign(&mut self, other: Factors) {
|
|
||||||
for (prime, exp) in &other.f {
|
|
||||||
self.add(*prime, *exp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Factors {
|
impl fmt::Display for Factors {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
for (p, exp) in self.f.iter() {
|
for (p, exp) in self.f.iter() {
|
||||||
|
@ -68,31 +59,32 @@ impl fmt::Display for Factors {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _factor<A: Arithmetic>(num: u64) -> Factors {
|
fn _factor<A: Arithmetic>(num: u64, f: Factors) -> Factors {
|
||||||
use miller_rabin::Result::*;
|
use miller_rabin::Result::*;
|
||||||
// Shadow the name, so the recursion automatically goes from “Big” arithmetic to small.
|
// Shadow the name, so the recursion automatically goes from “Big” arithmetic to small.
|
||||||
let _factor = |n| {
|
let _factor = |n, f| {
|
||||||
// TODO: Optimise with 32 and 64b versions
|
// TODO: Optimise with 32 and 64b versions
|
||||||
_factor::<A>(n)
|
_factor::<A>(n, f)
|
||||||
};
|
};
|
||||||
|
|
||||||
if num == 1 {
|
if num == 1 {
|
||||||
return Factors::one();
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
let n = A::new(num);
|
let n = A::new(num);
|
||||||
let divisor = match miller_rabin::test::<A>(n) {
|
let divisor = match miller_rabin::test::<A>(n) {
|
||||||
Prime => {
|
Prime => {
|
||||||
return Factors::prime(num);
|
let mut r = f;
|
||||||
|
r.push(num);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
Composite(d) => d,
|
Composite(d) => d,
|
||||||
Pseudoprime => rho::find_divisor::<A>(n),
|
Pseudoprime => rho::find_divisor::<A>(n),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut factors = _factor(divisor);
|
let f = _factor(divisor, f);
|
||||||
factors *= _factor(num / divisor);
|
_factor(num / divisor, f)
|
||||||
factors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn factor(mut n: u64) -> Factors {
|
pub fn factor(mut n: u64) -> Factors {
|
||||||
|
@ -113,16 +105,13 @@ pub fn factor(mut n: u64) -> Factors {
|
||||||
return factors;
|
return factors;
|
||||||
}
|
}
|
||||||
|
|
||||||
let (f, n) = table::factor(n);
|
let (factors, n) = table::factor(n, factors);
|
||||||
factors *= f;
|
|
||||||
|
|
||||||
if n < (1 << 32) {
|
if n < (1 << 32) {
|
||||||
factors *= _factor::<Montgomery>(n);
|
_factor::<Montgomery>(n, factors)
|
||||||
} else {
|
} else {
|
||||||
factors *= _factor::<Montgomery>(n);
|
_factor::<Montgomery>(n, factors)
|
||||||
}
|
}
|
||||||
|
|
||||||
factors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -14,8 +14,7 @@ use crate::Factors;
|
||||||
|
|
||||||
include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));
|
include!(concat!(env!("OUT_DIR"), "/prime_table.rs"));
|
||||||
|
|
||||||
pub(crate) fn factor(mut num: u64) -> (Factors, u64) {
|
pub(crate) fn factor(mut num: u64, mut factors: Factors) -> (Factors, u64) {
|
||||||
let mut factors = Factors::one();
|
|
||||||
for &(prime, inv, ceil) in P_INVS_U64 {
|
for &(prime, inv, ceil) in P_INVS_U64 {
|
||||||
if num == 1 {
|
if num == 1 {
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue