From b956e632e1d46c08500e759861462608272c5a87 Mon Sep 17 00:00:00 2001 From: nicoo Date: Tue, 16 Jun 2020 02:29:22 +0200 Subject: [PATCH 1/3] factor::table: Coalesce accesses to the `factors` table ~5.6% faster --- src/uu/factor/src/table.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/uu/factor/src/table.rs b/src/uu/factor/src/table.rs index e11b7198b..9d18c9d27 100644 --- a/src/uu/factor/src/table.rs +++ b/src/uu/factor/src/table.rs @@ -26,14 +26,18 @@ pub(crate) fn factor(mut num: u64) -> (Factors, u64) { // if (num * inv) mod 2^64 <= ceil, then prime divides num // See https://math.stackexchange.com/questions/1251327/ // for a nice explanation. + let mut k = 0; loop { let Wrapping(x) = Wrapping(num) * Wrapping(inv); // While prime divides num if x <= ceil { num = x; - factors.push(prime); + k += 1; } else { + if k > 0 { + factors.add(prime, k); + } break; } } From 9d992b77b2840b4846e68700aff2c36d4ca24dbc Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 20 Jun 2020 21:53:22 +0200 Subject: [PATCH 2/3] factor: Keep the primes table size in a single place --- src/uu/factor/build.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/uu/factor/build.rs b/src/uu/factor/build.rs index 1677e44eb..a045d66e6 100644 --- a/src/uu/factor/build.rs +++ b/src/uu/factor/build.rs @@ -39,12 +39,11 @@ fn main() { let mut file = File::create(&Path::new(&out_dir).join("prime_table.rs")).unwrap(); // By default, we print the multiplicative inverses mod 2^64 of the first 1k primes + const DEFAULT_SIZE: usize = 1027; let n = args() .nth(1) - .unwrap_or_else(|| "1027".to_string()) - .parse::() - .ok() - .unwrap_or(1027); + .and_then(|s| s.parse::().ok()) + .unwrap_or(DEFAULT_SIZE); write!(file, "{}", PREAMBLE).unwrap(); let mut cols = 3; From 8e040bbf1adc0e1ea7d755c212eac94f5d3e2f72 Mon Sep 17 00:00:00 2001 From: nicoo Date: Sat, 20 Jun 2020 21:54:03 +0200 Subject: [PATCH 3/3] factor::table: Optimise the size of the precomputed table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A too-large precomputed table actually slows down the program: we spend time fetching it from disk and from memory (into the CPU's cache), and larger prime factors are more unlikely to occur in random integers (prime p occurs with probability ~1/p when sampling 64b numbers uniformly-at-random) The new value was chosen after measuring the execution time (for all integers between 2 and 10⁷) for a broad set of values: | n | time (s) | |------|----------| | 16 | 40.84 | | 32 | 34.491 | | 64 | 29.044 | | 128 | 25.121 | | 192 | 23.98 | | 256 | 23.102 | | 256 | 24.93 | | 272 | 23.57 | | 288 | 23.85 | | 304 | 23.91 | | 320 | 23.24 | | 329 | 23.45 | | 336 | 23.55 | | 352 | 23.09 | | 368 | 23.65 | | 384 | 23.32 | | 384 | 23.36 | | 400 | 23.30 | | 416 | 23.38 | | 432 | 23.42 | | 448 | 23.95 | | 448 | 24.00 | | 464 | 23.81 | | 480 | 23.55 | | 496 | 24.10 | | 512 | 24.101 | | 512 | 24.23 | | 1027 | 29.864 | --- src/uu/factor/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uu/factor/build.rs b/src/uu/factor/build.rs index a045d66e6..719ca63bb 100644 --- a/src/uu/factor/build.rs +++ b/src/uu/factor/build.rs @@ -39,7 +39,7 @@ fn main() { let mut file = File::create(&Path::new(&out_dir).join("prime_table.rs")).unwrap(); // By default, we print the multiplicative inverses mod 2^64 of the first 1k primes - const DEFAULT_SIZE: usize = 1027; + const DEFAULT_SIZE: usize = 320; let n = args() .nth(1) .and_then(|s| s.parse::().ok())