From cee1837879f2ef14982a82fd93fb74376a64fc42 Mon Sep 17 00:00:00 2001 From: kwantam Date: Wed, 29 Apr 2015 02:54:24 -0400 Subject: [PATCH 01/11] slight clarification / refactoring in `unexpand` This keeps equivalent functionality but makes the code slightly cleaner. Also added one more test case. --- src/unexpand/unexpand.rs | 50 ++++++++++++++++------------------------ test/unexpand.rs | 6 ++++- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/unexpand/unexpand.rs b/src/unexpand/unexpand.rs index 3761c3477..ca7571461 100644 --- a/src/unexpand/unexpand.rs +++ b/src/unexpand/unexpand.rs @@ -142,14 +142,22 @@ fn next_tabstop(tabstops: &[usize], col: usize) -> Option { } } -fn write_tabs(mut output: &mut BufWriter, tabstops: &[usize], mut scol: usize, col: usize) { - while let Some(nts) = next_tabstop(tabstops, scol) { - if col < scol + nts { - break; - } +fn write_tabs(mut output: &mut BufWriter, tabstops: &[usize], + mut scol: usize, col: usize, prevtab: bool, init: bool, amode: bool) { + // This conditional establishes the following: + // We never turn a single space before a non-blank into + // a tab, unless it's at the start of the line. + let ai = init || amode; + if (ai && !prevtab && col > scol + 1) || + (col > scol && (init || ai && prevtab)) { + while let Some(nts) = next_tabstop(tabstops, scol) { + if col < scol + nts { + break; + } - safe_unwrap!(output.write_all("\t".as_bytes())); - scol += nts; + safe_unwrap!(output.write_all("\t".as_bytes())); + scol += nts; + } } while col > scol { @@ -194,15 +202,9 @@ fn unexpand(options: Options) { while byte < buf.len() { // when we have a finite number of columns, never convert past the last column if lastcol > 0 && col >= lastcol { - if (pctype != Tab && col > scol + 1) || - (col > scol && (init || pctype == Tab)) { - write_tabs(&mut output, ts, scol, col); - } else if col > scol { - safe_unwrap!(output.write_all(" ".as_bytes())); - } - scol = col; - + write_tabs(&mut output, ts, scol, col, pctype == Tab, init, true); safe_unwrap!(output.write_all(&buf[byte..])); + scol = col; break; } @@ -253,15 +255,8 @@ fn unexpand(options: Options) { } }, Other | Backspace => { // always - // never turn a single space before a non-blank into a tab - // unless it's at the start of the line - if (tabs_buffered && pctype != Tab && col > scol + 1) || - (col > scol && (init || (tabs_buffered && pctype == Tab))) { - write_tabs(&mut output, ts, scol, col); - } else if col > scol { - safe_unwrap!(output.write_all(" ".as_bytes())); - } - init = false; + write_tabs(&mut output, ts, scol, col, pctype == Tab, init, options.aflag); + init = false; // no longer at the start of a line col = if ctype == Other { // use computed width col + cwidth } else if col > 0 { // Backspace case, but only if col > 0 @@ -279,12 +274,7 @@ fn unexpand(options: Options) { } // write out anything remaining - if col > scol + 1 || (init && col > scol) { - write_tabs(&mut output, ts, scol, col); - } else if col > scol { - safe_unwrap!(output.write_all(" ".as_bytes())); - } - + write_tabs(&mut output, ts, scol, col, pctype == Tab, init, true); buf.truncate(0); // clear out the buffer } } diff --git a/test/unexpand.rs b/test/unexpand.rs index 8776a6fe2..59eaa9e06 100644 --- a/test/unexpand.rs +++ b/test/unexpand.rs @@ -105,4 +105,8 @@ fn unexpand_spaces_follow_tabs_1() { // evil assert_eq!(&out[..], b"a\t\t B \t" as &[u8]); } - +#[test] +fn unexpand_spaces_after_fields() { + let out = run(" \t A B C D A\t\n", &["-a"]); + assert_eq!(&out[..], b"\t\tA B C D\t\t A\t\n" as &[u8]); +} From 06b70877db5d48c919c31d8e4238fe1c64740c26 Mon Sep 17 00:00:00 2001 From: Wiktor Kuropatwa Date: Mon, 23 Feb 2015 14:29:27 +0100 Subject: [PATCH 02/11] factor: Rho-Pollard factorization implementation --- src/factor/factor.rs | 135 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 133 insertions(+), 2 deletions(-) diff --git a/src/factor/factor.rs b/src/factor/factor.rs index e3822bf4e..3271cee15 100644 --- a/src/factor/factor.rs +++ b/src/factor/factor.rs @@ -12,10 +12,14 @@ extern crate getopts; extern crate libc; +extern crate rand; use std::vec::Vec; use std::old_io::BufferedReader; use std::old_io::stdio::stdin_raw; +use std::cmp::{max,min}; +use std::mem::swap; +use rand::distributions::{IndependentSample, Range}; #[path="../common/util.rs"] #[macro_use] @@ -24,7 +28,76 @@ mod util; static VERSION: &'static str = "1.0.0"; static NAME: &'static str = "factor"; -fn factor(mut num: u64) -> Vec { +// computes (a + b) % m using the russian peasant algorithm +fn multiply(mut a: u64, mut b: u64, m: u64) -> u64 { + let mut result = 0; + while b > 0 { + if b & 1 > 0 { + result = (result + a) % m; + } + a = (a << 1) % m; + b >>= 1; + } + result +} + +// computes a.pow(b) % m +fn pow(mut a: u64, mut b: u64, m: u64) -> u64 { + let mut result = 1; + while b > 0 { + if b & 1 > 0 { + result = multiply(result, a, m); + } + a = multiply(a, a, m); + b >>= 1; + } + result +} + +fn witness(mut a: u64, exponent: u64, m: u64) -> bool { + if a == 0 { + return false; + } + if pow(a, m-1, m) != 1 { + return true; + } + a = pow(a, exponent, m); + if a == 1 { + return false; + } + loop { + if a == 1 { + return true; + } + if a == m-1 { + return false; + } + a = multiply(a, a, m); + } +} + +// uses the Miller-Rabin test +fn is_prime(num: u64) -> bool { + if num < 2 { + return false; + } + if num % 2 == 0 { + return num == 2; + } + let mut exponent = num - 1; + while exponent & 1 == 0 { + exponent >>= 1; + } + let witnesses = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; + for wit in witnesses.iter() { + if witness(*wit % num, exponent, num) { + return false; + } + } + true +} + +fn trial_division(mut num: u64) -> Vec { let mut ret = Vec::new(); if num < 2 { @@ -48,9 +121,67 @@ fn factor(mut num: u64) -> Vec { ret } +fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 { + (multiply(a, multiply(x, x, num), num) + b) % num +} + +fn gcd(mut a: u64, mut b: u64) -> u64 { + while b > 0 { + a %= b; + swap(&mut a, &mut b); + } + a +} + +fn rho_pollard_find_divisor(num: u64) -> u64 { + let range = Range::new(1, num); + let mut rng = rand::weak_rng(); + let mut x = range.ind_sample(&mut rng); + let mut y = x; + let mut a = range.ind_sample(&mut rng); + let mut b = range.ind_sample(&mut rng); + + loop { + x = rho_pollard_pseudorandom_function(x, a, b, num); + y = rho_pollard_pseudorandom_function(y, a, b, num); + y = rho_pollard_pseudorandom_function(y, a, b, num); + let d = gcd(num, max(x,y) - min(x,y)); + if d == num { + // Failure, retry with diffrent function + x = range.ind_sample(&mut rng); + y = x; + a = range.ind_sample(&mut rng); + b = range.ind_sample(&mut rng); + } else if d > 1 { + return d; + } + } +} + +fn rho_pollard_factor(num: u64) -> Vec { + let mut ret = Vec::new(); + if is_prime(num) { + ret.push(num); + return ret; + } + let divisor = rho_pollard_find_divisor(num); + ret.push_all(rho_pollard_factor(divisor).as_slice()); + ret.push_all(rho_pollard_factor(num/divisor).as_slice()); + ret +} + fn print_factors(num: u64) { print!("{}:", num); - for fac in factor(num).iter() { + + // Rho-Pollard is slower for small numbers and may cause 64-bit overflows + // for numbers bigger than 1 << 63, hence the constraints + let mut factors = if num < 1 << 63 && num > 1 << 40 { + rho_pollard_factor(num) + } else { + trial_division(num) + }; + factors.sort(); + for fac in factors.iter() { print!(" {}", fac); } println!(""); From 6c4e967fc666a7b40000c7cb271b5b3b448c3e0c Mon Sep 17 00:00:00 2001 From: kwantam Date: Wed, 29 Apr 2015 19:24:20 -0400 Subject: [PATCH 03/11] fix and slight optimization for `factor` This commit builds upon @wikol's Pollard rho implementation. It adds the following: 1. A generator for prime inverse tables. With these, we can do very fast divisibility tests (a single multiply and comparison) for small primes (presently, the first 1000 primes are in the table, which means all numbers of ~26 bits or less can be factored very quickly. 2. Always try prime inverse tables before jumping into Pollard's rho method or using trial division. 3. Since we have eliminated all small factors by the time we're done with the table division, only use slow trial division when the number is big enough to cause overflow issues in Pollard's rho, and jump out of trial division and into Pollard's rho as soon as the number is small enough. 4. Updates the Makefile to regenerate the prime table if it's not up-to-date. --- .gitignore | 1 + Makefile | 5 +- src/factor/deps.mk | 1 + src/factor/factor.rs | 219 ++++++++-------- src/factor/gen_table.rs | 169 +++++++++++++ src/factor/numeric.rs | 80 ++++++ src/factor/prime_table.rs | 517 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 875 insertions(+), 117 deletions(-) create mode 100644 src/factor/deps.mk create mode 100644 src/factor/gen_table.rs create mode 100644 src/factor/numeric.rs create mode 100644 src/factor/prime_table.rs diff --git a/.gitignore b/.gitignore index a2f1da53e..c40dace37 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +/src/*/gen_table /build/ /target/ /tmp/ diff --git a/Makefile b/Makefile index ddd4796f5..b6085bd85 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ RUSTCTESTFLAGS := $(RUSTCFLAGS) # Handle config setup ifeq ($(ENABLE_LTO),y) -RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -Z lto +RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -C lto else RUSTCBINFLAGS := $(RUSTCLIBFLAGS) endif @@ -305,6 +305,9 @@ $(BUILDDIR)/mkuutils: mkuutils.rs | $(BUILDDIR) $(SRCDIR)/cksum/crc_table.rs: $(SRCDIR)/cksum/gen_table.rs cd $(SRCDIR)/cksum && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table && $(RM) gen_table +$(SRCDIR)/factor/prime_table.rs: $(SRCDIR)/factor/gen_table.rs + cd $(SRCDIR)/factor && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table 1000 > $@ && $(RM) gen_table + crates: echo $(EXES) diff --git a/src/factor/deps.mk b/src/factor/deps.mk new file mode 100644 index 000000000..ea0f8a6b8 --- /dev/null +++ b/src/factor/deps.mk @@ -0,0 +1 @@ +DEPLIBS += rand diff --git a/src/factor/factor.rs b/src/factor/factor.rs index 3271cee15..273797bdf 100644 --- a/src/factor/factor.rs +++ b/src/factor/factor.rs @@ -1,10 +1,14 @@ #![crate_name = "factor"] -#![feature(collections, core, old_io, rustc_private)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. * * (c) T. Jameson Little +* (c) Wiktor Kuropatwa +* 20150223 added Pollard rho method implementation +* (c) kwantam +* 20150429 sped up trial division by adding table of prime inverses * * For the full copyright and license information, please view the LICENSE file * that was distributed with this source code. @@ -14,111 +18,47 @@ extern crate getopts; extern crate libc; extern crate rand; -use std::vec::Vec; -use std::old_io::BufferedReader; -use std::old_io::stdio::stdin_raw; -use std::cmp::{max,min}; +use numeric::*; +use prime_table::{P_INVS_U64, NEXT_PRIME}; +use std::cmp::{max, min}; +use std::io::{stdin, BufRead, BufReader, Write}; +use std::num::Wrapping; use std::mem::swap; -use rand::distributions::{IndependentSample, Range}; +use rand::weak_rng; +use rand::distributions::{Range, IndependentSample}; #[path="../common/util.rs"] #[macro_use] mod util; +mod numeric; +mod prime_table; static VERSION: &'static str = "1.0.0"; static NAME: &'static str = "factor"; -// computes (a + b) % m using the russian peasant algorithm -fn multiply(mut a: u64, mut b: u64, m: u64) -> u64 { - let mut result = 0; - while b > 0 { - if b & 1 > 0 { - result = (result + a) % m; - } - a = (a << 1) % m; - b >>= 1; - } - result -} - -// computes a.pow(b) % m -fn pow(mut a: u64, mut b: u64, m: u64) -> u64 { - let mut result = 1; - while b > 0 { - if b & 1 > 0 { - result = multiply(result, a, m); - } - a = multiply(a, a, m); - b >>= 1; - } - result -} - -fn witness(mut a: u64, exponent: u64, m: u64) -> bool { - if a == 0 { - return false; - } - if pow(a, m-1, m) != 1 { - return true; - } - a = pow(a, exponent, m); - if a == 1 { - return false; - } - loop { - if a == 1 { - return true; - } - if a == m-1 { - return false; - } - a = multiply(a, a, m); - } -} - -// uses the Miller-Rabin test -fn is_prime(num: u64) -> bool { - if num < 2 { - return false; - } - if num % 2 == 0 { - return num == 2; - } - let mut exponent = num - 1; - while exponent & 1 == 0 { - exponent >>= 1; - } - let witnesses = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; - for wit in witnesses.iter() { - if witness(*wit % num, exponent, num) { - return false; - } - } - true -} - -fn trial_division(mut num: u64) -> Vec { - let mut ret = Vec::new(); - - if num < 2 { - return ret; - } - while num % 2 == 0 { - num /= 2; - ret.push(2); - } - let mut i = 3; +fn trial_division_slow(mut num: u64, factors: &mut Vec) { + // assumption: this number has already been run through + // trial_division, which checks primes from the table. + // The first candidate we need to check is NEXT_PRIME. + let mut i = NEXT_PRIME; while i * i <= num { while num % i == 0 { num /= i; - ret.push(i); + factors.push(i); + if is_prime(num) { + factors.push(num); + return; + } + if num < 1 << 63 { + // once we're small enough, switch to Pollard's rho + return rho_pollard_factor(num, factors); + } } i += 2; } if num > 1 { - ret.push(num); + factors.push(num); } - ret } fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 { @@ -145,7 +85,7 @@ fn rho_pollard_find_divisor(num: u64) -> u64 { x = rho_pollard_pseudorandom_function(x, a, b, num); y = rho_pollard_pseudorandom_function(y, a, b, num); y = rho_pollard_pseudorandom_function(y, a, b, num); - let d = gcd(num, max(x,y) - min(x,y)); + let d = gcd(num, max(x, y) - min(x, y)); if d == num { // Failure, retry with diffrent function x = range.ind_sample(&mut rng); @@ -158,29 +98,73 @@ fn rho_pollard_find_divisor(num: u64) -> u64 { } } -fn rho_pollard_factor(num: u64) -> Vec { - let mut ret = Vec::new(); +fn rho_pollard_factor(num: u64, factors: &mut Vec) { if is_prime(num) { - ret.push(num); - return ret; + factors.push(num); + return; } let divisor = rho_pollard_find_divisor(num); - ret.push_all(rho_pollard_factor(divisor).as_slice()); - ret.push_all(rho_pollard_factor(num/divisor).as_slice()); - ret + rho_pollard_factor(divisor, factors); + rho_pollard_factor(num / divisor, factors); +} + +fn table_division(mut num: u64, factors: &mut Vec) { + if num < 2 { + return; + } + while num % 2 == 0 { + num /= 2; + factors.push(2); + } + if is_prime(num) { + factors.push(num); + return; + } + for &(prime, inv, ceil) in P_INVS_U64 { + if num == 1 { + break; + } + + // inv = prime^-1 mod 2^64 + // ceil = floor((2^64-1) / prime) + // if (num * inv) mod 2^64 <= ceil, then prime divides num + // See http://math.stackexchange.com/questions/1251327/ + // for a nice explanation. + loop { + let Wrapping(x) = Wrapping(num) * Wrapping(inv); // x = num * inv mod 2^64 + if x <= ceil { + num = x; + factors.push(prime); + if is_prime(num) { + factors.push(num); + return; + } + } else { + break; + } + } + } + + // do we still have more factoring to do? + // Decide whether to use Pollard Rho or slow divisibility based on + // number's size: + if num >= 1 << 63 { + // number is too big to use rho pollard without overflowing + trial_division_slow(num, factors); + } else if num > 1 { + // number is still greater than 1, but not so big that we have to worry + rho_pollard_factor(num, factors); + } } fn print_factors(num: u64) { print!("{}:", num); - // Rho-Pollard is slower for small numbers and may cause 64-bit overflows - // for numbers bigger than 1 << 63, hence the constraints - let mut factors = if num < 1 << 63 && num > 1 << 40 { - rho_pollard_factor(num) - } else { - trial_division(num) - }; + let mut factors = Vec::new(); + // we always start with table division, and go from there + table_division(num, &mut factors); factors.sort(); + for fac in factors.iter() { print!(" {}", fac); } @@ -188,21 +172,18 @@ fn print_factors(num: u64) { } fn print_factors_str(num_str: &str) { - let num = match num_str.parse::() { - Ok(x) => x, - Err(e)=> { crash!(1, "{} not a number: {}", num_str, e); } - }; - print_factors(num); + if let Err(e) = num_str.parse::().and_then(|x| Ok(print_factors(x))) { + show_warning!("{}: {}", num_str, e); + } } pub fn uumain(args: Vec) -> i32 { - let program = args[0].as_slice(); let opts = [ getopts::optflag("h", "help", "show this help message"), getopts::optflag("v", "version", "print the version and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => crash!(1, "Invalid options\n{}", f) }; @@ -214,22 +195,28 @@ pub fn uumain(args: Vec) -> i32 { \t{program} [NUMBER]...\n\ \t{program} [OPTION]\n\ \n\ - {usage}", program = program, version = VERSION, usage = getopts::usage("Print the prime factors of the given number(s). \ + {usage}", + program = &args[0][..], + version = VERSION, + usage = getopts::usage("Print the prime factors of the given number(s). \ If none are specified, read from standard input.", &opts)); return 1; } + if matches.opt_present("version") { - println!("{} {}", program, VERSION); + println!("{} {}", &args[0][..], VERSION); return 0; } if matches.free.is_empty() { - for line in BufferedReader::new(stdin_raw()).lines() { - print_factors_str(line.unwrap().as_slice().trim()); + for line in BufReader::new(stdin()).lines() { + for number in line.unwrap().split_whitespace() { + print_factors_str(number); + } } } else { for num_str in matches.free.iter() { - print_factors_str(num_str.as_slice()); + print_factors_str(num_str); } } 0 diff --git a/src/factor/gen_table.rs b/src/factor/gen_table.rs new file mode 100644 index 000000000..0cb9ea21a --- /dev/null +++ b/src/factor/gen_table.rs @@ -0,0 +1,169 @@ +/* +* This file is part of the uutils coreutils package. +* +* (c) kwantam +* +* For the full copyright and license information, please view the LICENSE file +* that was distributed with this source code. +*/ + +//! Generate a table of the multiplicative inverses of p_i mod 2^64 +//! for the first 10000 odd primes. +//! +//! 2 has no multiplicative inverse mode 2^64 because 2 | 2^64, +//! and in any case divisibility by two is trivial by checking the LSB. + +use std::env::args; +use std::iter::repeat; +use std::num::Wrapping; +use std::u64::MAX as MAX_U64; + +#[cfg(test)] +use numeric::is_prime; + +#[cfg(test)] +mod numeric; + +// A lazy Sieve of Eratosthenes +// Not particularly efficient, but fine for generating a few thousand primes. +struct Sieve { + inner: Box>, + filts: Vec, +} + +impl Iterator for Sieve { + type Item = u64; + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn next(&mut self) -> Option { + while let Some(n) = self.inner.next() { + if self.filts.iter().all(|&x| n % x != 0) { + self.filts.push(n); + return Some(n); + } + } + None + } +} + +impl Sieve { + #[inline] + pub fn new() -> Sieve { + fn next(s: &mut u64, t: u64) -> Option { + let ret = Some(*s); + *s = *s + t; + ret + } + let next = next; + + let odds_by_3 = Box::new(repeat(2).scan(3, next)) as Box>; + + Sieve { inner: odds_by_3, filts: Vec::new() } + } +} + +// extended Euclid algorithm +// precondition: a does not divide 2^64 +fn inv_mod_u64(a: u64) -> Option { + let mut t = 0u64; + let mut newt = 1u64; + let mut r = 0u64; + let mut newr = a; + + while newr != 0 { + let quot = if r == 0 { + // special case when we're just starting out + // This works because we know that + // a does not divide 2^64, so floor(2^64 / a) == floor((2^64-1) / a); + MAX_U64 + } else { + r + } / newr; + + let (tp, Wrapping(newtp)) = + (newt, Wrapping(t) - (Wrapping(quot) * Wrapping(newt))); + t = tp; + newt = newtp; + + let (rp, Wrapping(newrp)) = + (newr, Wrapping(r) - (Wrapping(quot) * Wrapping(newr))); + r = rp; + newr = newrp; + } + + if r > 1 { // not invertible + return None; + } + + Some(t) +} + +#[cfg_attr(test, allow(dead_code))] +fn main() { + // By default, we print the multiplicative inverses mod 2^64 of the first 10k primes + let n = args().skip(1).next().unwrap_or("10000".to_string()).parse::().ok().unwrap_or(10000); + + print!("{}", PREAMBLE); + + let m = n; + Sieve::new() + .scan((0, 3), move |st, x| { + let (count, mut cols) = *st; + if count < m { + // format the table + let outstr = format!("({}, {}, {}),", x, inv_mod_u64(x).unwrap(), MAX_U64 / x); + if cols + outstr.len() > MAX_WIDTH { + print!("\n {}", outstr); + cols = 4 + outstr.len(); + } else { + print!(" {}", outstr); + cols += 1 + outstr.len(); + } + + *st = (count + 1, cols); + Some(1) + } else if count == m { + // now we're done formatting the table, print NEXT_PRIME + print!("\n];\n\npub const NEXT_PRIME: u64 = {};\n", x); + + *st = (count + 1, cols); + Some(1) + } else { + None + } + }).take(m + 1).count(); +} + +#[test] +fn test_generator_and_inverter() { + let num = 10000; + + let invs = Sieve::new().map(|x| inv_mod_u64(x).unwrap()); + assert!(Sieve::new().zip(invs).take(num).all(|(x, y)| { + let Wrapping(z) = Wrapping(x) * Wrapping(y); + is_prime(x) && z == 1 + })); +} + +const MAX_WIDTH: usize = 100; +const PREAMBLE: &'static str = +r##"/* +* This file is part of the uutils coreutils package. +* +* (c) kwantam +* +* For the full copyright and license information, please view the LICENSE file +* that was distributed with this source code. +*/ + +// *** NOTE: this file was automatically generated. +// Please do not edit by hand. Instead, modify and +// re-run src/factor/gen_tables.rs. + +pub const P_INVS_U64: &'static [(u64, u64, u64)] = &[ + "##; diff --git a/src/factor/numeric.rs b/src/factor/numeric.rs new file mode 100644 index 000000000..0d3888f65 --- /dev/null +++ b/src/factor/numeric.rs @@ -0,0 +1,80 @@ +/* +* This file is part of the uutils coreutils package. +* +* (c) Wiktor Kuropatwa +* +* For the full copyright and license information, please view the LICENSE file +* that was distributed with this source code. +*/ + +// computes (a + b) % m using the russian peasant algorithm +pub fn multiply(mut a: u64, mut b: u64, m: u64) -> u64 { + let mut result = 0; + while b > 0 { + if b & 1 > 0 { + result = (result + a) % m; + } + a = (a << 1) % m; + b >>= 1; + } + result +} + +// computes a.pow(b) % m +fn pow(mut a: u64, mut b: u64, m: u64) -> u64 { + let mut result = 1; + while b > 0 { + if b & 1 > 0 { + result = multiply(result, a, m); + } + a = multiply(a, a, m); + b >>= 1; + } + result +} + +fn witness(mut a: u64, exponent: u64, m: u64) -> bool { + if a == 0 { + return false; + } + if pow(a, m-1, m) != 1 { + return true; + } + a = pow(a, exponent, m); + if a == 1 { + return false; + } + loop { + if a == 1 { + return true; + } + if a == m-1 { + return false; + } + a = multiply(a, a, m); + } +} + +// uses deterministic (i.e., fixed witness set) Miller-Rabin test +pub fn is_prime(num: u64) -> bool { + if num < 2 { + return false; + } + if num % 2 == 0 { + return num == 2; + } + let mut exponent = num - 1; + while exponent & 1 == 0 { + exponent >>= 1; + } + + // These witnesses detect all composites up to at least 2^64. + // Discovered by Jim Sinclair, according to http://miller-rabin.appspot.com + let witnesses = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; + for wit in witnesses.iter() { + if witness(*wit % num, exponent, num) { + return false; + } + } + true +} diff --git a/src/factor/prime_table.rs b/src/factor/prime_table.rs new file mode 100644 index 000000000..15e035be3 --- /dev/null +++ b/src/factor/prime_table.rs @@ -0,0 +1,517 @@ +/* +* This file is part of the uutils coreutils package. +* +* (c) kwantam +* +* For the full copyright and license information, please view the LICENSE file +* that was distributed with this source code. +*/ + +// *** NOTE: this file was automatically generated. +// Please do not edit by hand. Instead, modify and +// re-run src/factor/gen_tables.rs. + +pub const P_INVS_U64: &'static [(u64,u64,u64)] = &[ + (3,12297829382473034411,6148914691236517205), (5,14757395258967641293,3689348814741910323), + (7,7905747460161236407,2635249153387078802), (11,3353953467947191203,1676976733973595601), + (13,5675921253449092805,1418980313362273201), (17,17361641481138401521,1085102592571150095), + (19,9708812670373448219,970881267037344821), (23,15238614669586151335,802032351030850070), + (29,3816567739388183093,636094623231363848), (31,17256631552825064415,595056260442243600), + (37,1495681951922396077,498560650640798692), (41,10348173504763894809,449920587163647600), + (43,9437869060967677571,428994048225803525), (47,5887258746928580303,392483916461905353), + (53,2436362424829563421,348051774975651917), (59,14694863923124558067,312656679215416129), + (61,5745707170499696405,302405640552615600), (67,17345445920055250027,275324538413575397), + (71,1818693077689674103,259813296812810586), (73,9097024474706080249,252695124297391118), + (79,11208148297950107311,233503089540627235), (83,11779246215742243803,222249928598910260), + (89,17617676924329347049,207266787345051141), (97,11790702397628785569,190172619316593315), + (101,4200743699953660269,182641030432767837), (103,15760325033848937303,179094602657374287), + (107,8619973866219416643,172399477324388332), (109,12015769075535579493,169236184162472950), + (113,10447713457676206225,163245522776190722), (127,9150747060186627967,145249953336295682), + (131,281629680514649643,140814840257324821), (137,16292379802327414201,134647766961383588), + (139,4246732448623781667,132710389019493177), (149,16094474695182830269,123803651501406386), + (151,8062815290495565607,122163868037811600), (157,6579730370240349621,117495185182863386), + (163,2263404180823257867,113170209041162893), (167,10162278172342986519,110459545351554201), + (173,9809829218388894501,106628578460748853), (179,17107036403551874683,103054436165975148), + (181,3770881385233444253,101915713114417412), (191,2124755861893246783,96579811904238490), + (193,8124213711219232577,95578984837873324), (197,14513935692512591373,93638294790403815), + (199,2780916192016515319,92697206400550510), (211,13900627050804827995,87425327363552377), + (223,7527595115280579359,82720825442643729), (227,1950316554048586955,81263189752024456), + (229,2094390156840385773,80553467570784068), (233,7204522363551799129,79170575423646144), + (239,7255204782128442895,77183029597111094), (241,17298606475760824337,76542506529915151), + (251,2939720171109091891,73493004277727297), (257,18374966859414961921,71777214294589695), + (263,15430736487513693367,70139711306880424), (269,10354863773718001093,68575256779589411), + (271,15383631589145234927,68069166323651481), (277,17181443938689762877,66594743948409933), + (281,14245350405676059433,65646776063023315), (283,5149444458738708755,65182841249857072), + (293,2707201348701401773,62958170900032599), (307,17305088903023944187,60087114246610917), + (311,9134400602415662215,59314289626075728), (313,6365010734698503433,58935284580541698), + (317,17050145153302519317,58191621683626345), (331,3455281367280943203,55730344633563600), + (337,9196002980365592497,54738112978366622), (347,9941040754419844819,53160645745560667), + (349,15751088062938241781,52856000211202153), (353,8779186981255537313,52257065364616293), + (359,5600822016808749655,51383688227603207), (367,9751139919072624015,50263607830271257), + (373,3511310534137743069,49455077945602015), (379,17181268226964305331,48672147951740241), + (383,14834457375202459263,48163822646761231), (389,12661389891209383757,47420935922132523), + (397,185861401246443845,46465350311610961), (401,3220129888178724721,46001855545410353), + (409,2074694932495450793,45102063749901104), (419,1849076971589024267,44025642180691053), + (421,14897608040525528621,43816494236839790), (431,8046375605237577039,42799870240625409), + (433,7540585914657253201,42602180308798040), (439,15379290047785184263,42019918163347497), + (443,15615189678648040307,41640505809728107), (449,205420312624827969,41084062524965593), + (457,686202733595322489,40364866682077793), (461,3041111821262312197,40014629227135686), + (463,8127723090792113455,39841779856824085), (467,15247201739725667931,39500522641776341), + (479,8010277176057592351,38510947961815347), (487,2386334448960373207,37878324586672590), + (491,1051952818867347139,37569743530976683), (499,12494988971771199291,36967422993405915), + (503,17969989256695189447,36673447462643243), (509,5436172123882971989,36241147492553146), + (521,1805727346946616377,35406418567580713), (523,7195288319381928355,35271021173440825), + (541,13911777416032342069,34097493666745936), (547,13219604528142859659,33723480939139948), + (557,5133295029488295333,33118032448311582), (563,18151858289227516155,32765087164670606), + (569,6386658317259721737,32419585366800617), (571,1873749835858413299,32306031652731263), + (577,8184343991108570561,31970093715267853), (587,8107768264083584867,31425458387920871), + (593,13407330009728190129,31107494222107169), (599,16999336775772408167,30795899956109435), + (601,10926856722530117097,30693417759916059), (607,7810235958720518559,30390023185682951), + (613,10111102787547160429,30092567820080834), (617,5112468778937331161,29897478239399597), + (619,10400506755613301315,29800878955912038), (631,14909412801254946631,29234142747558718), + (641,18417966001831689601,28778071877862015), (643,12450835035754191915,28688559990217032), + (647,16650538700226241335,28511196404496988), (653,18023005695293558853,28249225227732850), + (659,13744083976011213723,27992024391061535), (661,3544230707051608253,27907328401981167), + (673,7016889276180750689,27409723735081057), (677,7711120491668837677,27247775588935822), + (683,18338710433453565955,27008410063996415), (691,16604739238563445883,26695722248494285), + (701,4578792394900801685,26314898821268975), (709,17796294705807240205,26017974716092456), + (719,7799457855921701935,25656111368163493), (727,3501582781529460967,25373788271952615), + (733,8027982755134170485,25166090141486427), (739,12755461734324196043,24961764646426998), + (743,8416482154761154775,24827380987496031), (751,73688724661955599,24562908220651866), + (757,11233750354002778461,24368222026036395), (761,8193166224591101769,24240136759145271), + (769,8635666926574042369,23987963684927895), (773,11955781087876436429,23863834506739394), + (787,1757948926973591323,23439319026314550), (797,3332912354597459765,23145224684704581), + (809,12062209660064712985,22801908620160137), (811,2229076349227541379,22745677032934095), + (821,4044353146489304861,22468628591607249), (823,5536264624794968711,22414026821032261), + (827,9502192231439261171,22305615566758829), (829,9813044796750195733,22251802260204525), + (839,17941052639030982263,21986584116459537), (853,13018686907823153661,21625725760503577), + (857,12247604875076703465,21524788884141833), (859,858986918449804499,21474672961245112), + (863,13637338028999645343,21375137976488472), (877,4964004106494246501,21033915705484095), + (881,14447506709261737361,20938415520669184), (883,17047047751015848379,20890989890950794), + (887,15763959422628906567,20796780240935232), (907,11979197639928253475,20338196332645591), + (911,16462352285319281519,20248895799900715), (919,16098246732442938407,20072626848432591), + (929,13264181960428396641,19856559821000593), (937,11792529028977610905,19687026759561954), + (941,1725094026021722149,19603341204792297), (947,18271431828024877947,19479138409408185), + (953,18137040080866579081,19356499552685783), (967,9614435380713147895,19076260676018150), + (971,10828675717831559651,18997676697950104), (977,12064963626510136625,18881007240234955), + (983,9326583728009813991,18765762028188760), (991,13160290676198438943,18614272526447579), + (997,11785933776281829869,18502250826188115), (1009,6965519813759503633,18282204235589248), + (1013,7775675932353384541,18210013893099261), (1019,10372899268140896051,18102791043875909), + (1021,7497942008412795221,18067330140753723), (1031,13544311604071901623,17892089305246897), + (1033,15464550210873641529,17857448280454551), (1039,1881958490676816623,17754325383743553), + (1049,8370495880920635433,17585075380085368), (1051,15691141010367591955,17551611868420125), + (1061,10466484384894580653,17386186685871396), (1063,5917535022704569239,17353475139896097), + (1069,13511506650808773541,17256074905247475), (1087,4836542834413267903,16970325734783396), + (1091,12613447368457676907,16908106392034419), (1093,12235946434985750157,16877167496532069), + (1097,14007418243755748857,16815628143764404), (1103,13546566364192871087,16724156005176384), + (1109,14687533829653321981,16633673646266502), (1117,17043007953507839989,16514542590608372), + (1123,10923494932339137867,16426308168931034), (1129,8610659102608444377,16339011579902171), + (1151,2852754513571068799,16026710750399262), (1153,16894849732729650049,15998910731751562), + (1163,14877941479913636643,15861344861315177), (1171,10554499171123313051,15752983837497482), + (1181,9918444103984390581,15619597014148646), (1187,6884505159775342347,15540643701524474), + (1193,17503532515875282841,15462484554660143), (1201,10275496907003905105,15359487155461741), + (1213,12439766407497455253,15207538395473661), (1217,6745111842892974913,15157554703130280), + (1223,5399782811437464823,15083192210719175), (1229,11572367518982965253,15009555796346258), + (1231,1168843247562424879,14985169840543908), (1237,12988774525627339901,14912485104049758), + (1249,2171073962238033697,14769210627469616), (1259,2754557494723904451,14651901567680342), + (1277,8710561218830743637,14445375155606540), (1279,10802667170608642815,14422786609624356), + (1283,17756608675784330667,14377820790108769), (1289,715544766241642809,14310895324832856), + (1291,10173572254439349923,14288725076459761), (1297,9401154844041645041,14222624574949538), + (1301,4069343235322552893,14178896290322483), (1303,17455744775812645543,14157132827098658), + (1307,11545093077501463827,14113805718216948), (1319,7286393982109686423,13985401117293064), + (1321,10375420777264342809,13964227156479600), (1327,17848997280062595535,13901088224347815), + (1361,8864195903163884465,13553816365694012), (1367,11915490136858474087,13494326315808011), + (1373,7241656996161287925,13435356208091443), (1381,10365440551193781357,13357526483497140), + (1399,11511084757933122631,13185664098434275), (1409,11062809611273648769,13092082380205501), + (1423,11991031811792927087,12963277634370731), (1427,10910337770294927515,12926940486131430), + (1429,4001742941112638909,12908848197137544), (1433,6539390083352723113,12872815124710084), + (1439,3589359513994909279,12819141121410390), (1447,15973580044476895767,12748268191920906), + (1451,6496406768894266627,12713124792356686), (1453,16301183338364118565,12695625652931556), + (1459,12921571242858918267,12643416088903051), (1471,15612641993044453951,12540274693208396), + (1481,7535638193514030201,12455600319857901), (1483,10846635760131307491,12438802477214802), + (1487,7517637463798243631,12405342349502052), (1489,9155234298503263025,12388679700275051), + (1493,17211195240909179773,12355488328003718), (1499,11419998999601376851,12306033404742862), + (1511,5310611298519956951,12208301835678061), (1523,3355054568888736571,12112110356999048), + (1531,13325995392242171187,12048820426982071), (1543,7651274275550300087,11955116055547343), + (1549,15826806245293734085,11908808310980988), (1553,14028077753413380849,11878135269613362), + (1559,9773579605442007463,11832420829832938), (1567,5579934072072959455,11772012810280505), + (1571,4004035473669609867,11742039512227594), (1579,17874299197451307139,11682548495066213), + (1583,11163601277709254863,11653028473600474), (1597,8663154699613126933,11550872932817502), + (1601,13918592655241185729,11522013787451312), (1607,1503748272343466871,11478994445369976), + (1609,4574425659049167865,11464725962529242), (1613,2904818967589724805,11436295147991042), + (1619,3999263230310100443,11393912337065813), (1621,9707015851248764669,11379854456329149), + (1627,10045368930120874451,11337888182980670), (1637,13127951646836669293,11268628023035767), + (1657,2237655738573095881,11132615614791521), (1663,5291098570751326591,11092449833860223), + (1667,12747839935760889899,11065833277570216), (1669,12312566146262696525,11052572842246585), + (1693,14633182097455361973,10895891360726256), (1697,3782832609104846177,10870208646853006), + (1699,15080946155610692875,10857412639028576), (1709,5137887758388383013,10793881845353745), + (1721,4062356771607158665,10718619450150814), (1723,2141235527998787187,10706177639993935), + (1733,18372233278258907149,10644399350092066), (1741,3401151549489239557,10595487693112895), + (1747,8806287668845887835,10559097924275644), (1753,5387754116223211881,10522957258248460), + (1759,4184338195230307615,10487063145940620), (1777,7816768873102584337,10380835156842741), + (1783,6114428349726497479,10345902453005917), (1787,17001559870956704819,10322744305377477), + (1789,18085851931406681685,10311204065796283), (1801,15916846357881534265,10242500873797641), + (1811,13751024019606788891,10185943718227251), (1823,16463440816196072671,10118894170987137), + (1831,11374316799136037015,10074682727312698), (1847,10307005892836089479,9987408810887683), + (1861,10526836220461872013,9912275160510237), (1867,12903828473628641891,9880419964493600), + (1871,5176130752911552431,9859296672212480), (1873,10567728986166763953,9848768859428484), + (1877,8451891264459357693,9827780540069020), (1879,13538084128603231335,9817319890212640), + (1889,13896091485912489121,9765348900852065), (1901,9383483176894863973,9703705456975040), + (1907,2843913349591299515,9673174658473807), (1913,12053544219622027977,9642835375697622), + (1931,10661090826649331747,9552948769399042), (1933,6680145293117788997,9543064704453984), + (1949,13790100623599187637,9464722459573910), (1951,7043989920509285471,9455020027529242), + (1973,17128451669050125981,9349591522407274), (1979,736378363730699635,9321245110515185), + (1987,11864589293508206827,9283716192103448), (1993,11727057070441546361,9255767222132238), + (1997,13994400236189269253,9237227878672784), (1999,2768395808960913199,9227986029869710), + (2003,16319336244939253851,9209557700304319), (2011,15043590393278798931,9172920971511462), + (2017,493864243916864545,9145634146608602), (2027,11384744369122175171,9100515083231155), + (2029,5309462069515218405,9091544639580853), (2039,9698337247188150727,9046956387302379), + (2053,11797649765601871053,8985262578523892), (2063,3818109413220542191,8941708227682768), + (2069,3798121302755084093,8915777705997849), (2081,15698790847928695777,8864365244454373), + (2083,13345772116697212811,8855854092035310), (2087,12993154666196952983,8838880725304049), + (2089,7205621428505023513,8830418417285568), (2099,9913257415504704251,8788348772610553), + (2111,6859637185154901951,8738391318668664), (2113,34920480972474305,8730120243118576), + (2129,5588609641870672049,8664511072667708), (2131,16317274790681607131,8656379199300587), + (2137,13327923654566002665,8632074905806996), (2141,15749952436590873589,8615947722423891), + (2143,11310789413371138975,8607906707283971), (2153,15473673849103321049,8567925719326312), + (2161,6700922766248032401,8536207345538894), (2179,4893170295825663531,8465692553331597), + (2203,10433337773872946579,8373465308084226), (2207,10364278500860826463,8358289113597440), + (2213,8552354007964753709,8335627688074808), (2221,17059708386942556965,8305602914772423), + (2237,16393440866577822357,8246197619002928), (2239,15110017253766555455,8238831654180237), + (2243,14104398611864414187,8224139132282457), (2251,6883725020842302691,8194910739097979), + (2267,13865572078341894995,8137072815928342), (2269,4089339915855400821,8129900429135985), + (2273,15021963607759076129,8115593521209657), (2281,16036779262676914009,8087130238364555), + (2287,14583171528319575567,8065913455928968), (2293,13072812524979512157,8044807707679699), + (2297,4946971854333950281,8030798464827841), (2309,9770622781354171341,7989061963494825), + (2311,191571552474698935,7982148019779122), (2333,13362622153694445877,7906877014020382), + (2339,9984428387052711563,7886594302569282), (2341,12907204952044530349,7879856503079688), + (2347,10532014085543587203,7859712004137005), (2351,17214868778272546255,7846339461382199), + (2357,1017427547552923933,7826365750407107), (2371,18298921156206185323,7780153552808752), + (2377,18058718325419489529,7760514965801241), (2381,17276874961937127301,7747477561406783), + (2383,10241310285152218543,7740975272223899), (2389,13551291690816351229,7721533726960883), + (2393,2227793162265800425,7708626859051212), (2399,3252593890445660831,7689347258736786), + (2411,9357265865676806979,7651075932687495), (2417,5975920814941902737,7632082777703579), + (2423,2047946411815051335,7613183687044800), (2437,499583548980234061,7569447711821728), + (2441,15590181492856536249,7557043864690516), (2447,5435268687022716271,7538514129019023), + (2459,7749282890663670931,7501725934814783), (2467,14722999222186504715,7477399300247082), + (2473,12524093530027633305,7459257611690073), (2477,11342103845078581797,7447211979697033), + (2503,16596910768675153911,7369853804917919), (2521,18227227087509120617,7317232873347699), + (2531,6646950057377760203,7288322431335263), (2539,3465575786986788547,7265358043997460), + (2543,3358569605240866063,7253930032917637), (2549,10949362017858984541,7236855266265026), + (2551,16769109959597197255,7231181526346355), (2557,13101011825520745301,7214213560308780), + (2579,13311124746480603163,7152673157700485), (2591,17656474451099840991,7119546149637032), + (2593,8330558160552983009,7114054791249345), (2609,14154994877564784337,7070427011770621), + (2617,2283815468048106505,7048813172987983), (2621,15624483725156506901,7038055732052480), + (2633,11910165182417864697,7005979519069332), (2647,13603341304072929639,6968924848398017), + (2657,5963776123190253985,6942696301734870), (2659,7978095406079723339,6937474266156281), + (2663,4419460277516595543,6927053726515040), (2671,3549841427887199375,6906306279936185), + (2677,15855793094361478621,6890827072734236), (2683,3417082297664423091,6875417097916344), + (2687,14849388697965671807,6865182014778396), (2689,8472193726675826049,6860075892045203), + (2693,575390457553509965,6849886399446547), (2699,12705630690265304355,6834658789814580), + (2707,16695427772659180443,6814460315371094), (2711,10390327628386014503,6804405781523257), + (2713,8540033378761222569,6799389632771674), (2719,7639218031260373343,6784385462931059), + (2729,2142769465506019737,6759525127779242), (2731,13509149815971843,6754574907985921), + (2741,5155128041029374877,6729932168445659), (2749,7414933503619154069,6710347062098781), + (2753,8831387101034939713,6700597193501471), (2767,16100067559815167023,6666694641745410), + (2777,11511777990543267177,6642687819124793), (2789,14842055826964587245,6614106874761402), + (2791,10931893478292941015,6609367278290774), (2797,5111271597112943333,6595189157565088), + (2801,3839504389493990929,6585770822459675), (2803,14017682795933408827,6581071735180004), + (2819,9318255963448883115,6543719075455676), (2833,8647114765226362353,6511381600321055), + (2837,12601265426453687357,6502200942442563), (2843,10822781960938280723,6488478393847890), + (2851,1067594799074737291,6470271509543862), (2857,17813989114233340185,6456683259961341), + (2861,1972982763563482277,6447656090076739), (2879,12129102650757964991,6407344242344408), + (2887,9181839706934750839,6389589218465379), (2897,7144372402727689649,6367533335764429), + (2903,2923011461903683687,6354372743268877), (2909,16893133795930644725,6341266439913905), + (2917,9106380344923467373,6323875239530185), (2927,5123745449923425167,6302269926105074), + (2939,12345949504248617907,6276537622902195), (2953,12487315070553807545,6246780925739773), + (2957,386776507463642949,6238330765542628), (2963,273930725360519835,6225698303648178), + (2969,15172431467833858217,6213116899194864), (2971,13150523038746829459,6208934390343167), + (2999,8051613201895899655,6150965012907486), (3001,12760893267917703817,6146865735991186), + (3011,3394053874737659115,6126451037432597), (3019,6091886002480431587,6110216652437744), + (3023,14938018356745280303,6102131681676993), (3037,15847071217750484085,6074001999904363), + (3041,16426761904506894369,6066012520128099), (3049,3817610859465636953,6050096449232388), + (3061,17295705812331399261,6026378331822787), (3067,4559058365788014387,6014588873071259), + (3079,17218558774875365815,5991147799191150), (3083,1352242672934920099,5983374659004071), + (3089,13579765627586766065,5971752694629184), (3109,5684136642847780781,5933336787941316), + (3119,3761503440487103183,5914313585671545), (3121,4604297863960186065,5910523573761471), + (3137,12819222850075493313,5880377454163070), (3163,17274503934975558611,5832040491213895), + (3167,14584984894401236895,5824674478594743), (3169,10111074299789678497,5820998445474771), + (3181,3635997653007195493,5799039318990742), (3187,11414176125935122619,5788121767715579), + (3191,11781405334446902599,5780866209247744), (3203,8730959730172863019,5759208265285529), + (3209,1965966492118624697,5748440035434575), (3217,17322851677549442161,5734144878367905), + (3221,10663718554873388733,5727023928503431), (3229,5541449907555981749,5712834956243280), + (3251,15479150363912536699,5674175353340372), (3253,9611814080829292957,5670686773350615), + (3257,10279656276875295113,5663722466597958), (3259,3792365305119791219,5660246724059389), + (3271,2227595203031266551,5639481526661434), (3299,7162861218072729803,5591616875934995), + (3301,14054396045252808941,5588229043838095), (3307,9131333549640924099,5578090134172830), + (3313,11926630185899746321,5567987948599321), (3319,17407412605862704327,5557922287951055), + (3323,9281659973289909811,5551232041441333), (3329,4327698144057422593,5541226816974932), + (3331,1030049353860695467,5537899751939222), (3343,7432774234904805871,5518020961325022), + (3347,16142967849386099995,5511426373979549), (3359,15481206175584169695,5491736848380336), + (3361,18139389813629892321,5488468929993915), (3371,2670427501622741379,5472187503325289), + (3373,306260796954561189,5468942802760021), (3389,6221489665461793301,5443123066895707), + (3391,9770083266405884607,5439912731851828), (3407,3021216082515388847,5414365739274890), + (3413,12685176777320925181,5404847369970568), (3433,445988860506231513,5373359765135319), + (3449,8824913807370472649,5348432610527559), (3457,1371366279127380609,5336055560806928), + (3461,4130663581948830541,5329888492837200), (3463,3861937468506908727,5326810301388839), + (3467,10822231740964876835,5320664572745760), (3469,13655589155746938181,5317597023265941), + (3491,1976248147684724235,5284085956376268), (3499,13986628187353941251,5272004593800957), + (3511,2553437089097932807,5253985780036898), (3517,14135335592450168213,5245022483283921), + (3527,8849416210013201399,5230151424357684), (3529,17944934090406599801,5227187326072414), + (3533,13136713300156589829,5221269197200552), (3539,10956500718546899547,5212417087795860), + (3541,16279603284479624061,5209473051033479), (3547,10453328330464110163,5200660860927417), + (3557,9894964209344341997,5186039942004372), (3559,14139566685327242711,5183125617788578), + (3571,16742060359253054267,5165708225625749), (3581,13120317552565827413,5151282902460081), + (3583,10631461488197104127,5148407500337580), (3593,16916788678784573497,5134078506459658), + (3607,1493332206687881639,5114151392766717), (3613,8536660971835696181,5105658475978287), + (3617,17268641258938496481,5100012185156082), (3623,12876570732103631255,5091566125782376), + (3631,2667182770227902671,5080348133767433), (3637,15180397308939424797,5071967026040569), + (3643,4501552424245893875,5063613525585932), (3659,720930418841340771,5041471460428956), + (3671,13738326967453531495,5024991575513361), (3673,8708590858647525865,5022255397143901), + (3677,10826237071271474677,5016791970005317), (3691,11394900159322074691,4997763227772839), + (3697,419130782307709585,4989652170329876), (3701,3982423268007006685,4984259409270346), + (3709,10165851951108741845,4973508782342828), (3719,3625859079828363063,4960135540120879), + (3727,11992610917788635247,4949488616503770), (3733,1319389410040302781,4941533370937463), + (3739,17015999013165082515,4933603657049893), (3761,13002477675991497297,4904744502448697), + (3767,783509172230827783,4896932326442673), (3769,9925708936450774921,4894333795094070), + (3779,10304598237523382763,4881382395795065), (3793,9454381882228148785,4863365165755220), + (3797,10522951715474029181,4858241789230853), (3803,6330002896710745427,4850576932345398), + (3821,16868077412599103205,4827726792386692), (3823,14620359545733701647,4825201170209142), + (3833,3157073861819323209,4812612594236773), (3847,15996448721054084791,4795098537486236), + (3851,15850500166165906595,4790117910597131), (3853,15722581764355610565,4787631475138736), + (3863,16379066055610603687,4775237917087639), (3877,7550937024755496109,4757994344521421), + (3881,4515435936620477721,4753090459600502), (3889,6147333586918894033,4743312952869517), + (3907,8753586770580370795,4721459962556834), (3911,10055857418856753783,4716631059501291), + (3917,18117085639918469509,4709406197015458), (3919,5671938404904314799,4707002825646734), + (3923,15126988448922668251,4702203434542327), (3929,10653006440123943145,4695022670834703), + (3931,4368842211300837587,4692633954136238), (3943,9408166962269822039,4678352542153069), + (3947,15553778636256748867,4673611369067532), (3967,9128046033953075327,4650048922034169), + (3989,3838254595432170429,4624403127026711), (4001,9935699444849808481,4610533385081117), + (4003,16838471857440594955,4608229846042855), (4007,10680420826305505303,4603629666510993), + (4013,14433784298890603557,4596746592003376), (4019,8147044222651021179,4589884069099166), + (4021,13845380157785482909,4587601112586309), (4027,1575783452037766515,4580765848946995), + (4049,715272615355001137,4555876530923574), (4051,9325828650446102619,4553627270725636), + (4057,2259805719653351529,4546892796083202), (4073,17463944303516825689,4529031199044819), + (4079,10862730881355808527,4522369226209745), (4091,1848732600885093171,4509103904597788), + (4093,7918624318961075541,4506900579943696), (4099,5944900932268923563,4500303506638095), + (4111,12196120260847132399,4487167130554500), (4127,250307164557241311,4469770795665023), + (4129,15189859493972505569,4467605733521325), (4133,14023631715363031981,4463281895405166), + (4139,13931993712108252803,4456811808096050), (4153,1159306574341004809,4441787641153275), + (4157,4406451013998937877,4437513609263784), (4159,7069995204013711295,4435379676294674), + (4177,13182554718703138993,4416266237421487), (4201,10204768680623898585,4391036437445739), + (4211,6965168149417759931,4380608899004880), (4217,12773178253552736713,4374376114230389), + (4219,7913867450441879219,4372302458807668), (4229,14778332684258207821,4361963602201360), + (4231,248514396644160823,4359901695511593), (4241,13549070452630335601,4349621333107651), + (4243,12334059141436247451,4347571075585564), (4253,17570599633810814389,4337348712369986), + (4259,15835007357004489483,4331238336160965), (4261,15078622297284761389,4329205368155257), + (4271,15401800366857471567,4319069087733446), (4273,14306695497372678225,4317047524855968), + (4283,11396237408133428339,4306968030284742), (4289,6829897316169449281,4300942894313255), + (4297,10826783466114845049,4292935553574482), (4327,3465958616114135767,4263171729537682), + (4337,4249088616471257105,4253341958429686), (4339,3804986389944698939,4251381441278993), + (4349,8788607431760448597,4241605903359289), (4357,1752800561513829325,4233817781434370), + (4363,4879106729557832355,4227995432892402), (4373,14042810661188908605,4218327023487205), + (4391,17963625064719208087,4201034860785595), (4397,15606524438071305893,4195302268298738), + (4409,3782231037113502985,4183883890612282), (4421,1969432979595319693,4172527499142626), + (4423,1259533508989438071,4170640758243172), (4441,1013511721230608105,4153736562420525), + (4447,10581885345633700511,4148132240546334), (4451,14928144721074321483,4144404420065053), + (4457,15160516836885368537,4138825235294940), (4463,8303721452852899215,4133261051693827), + (4481,14552385695283031681,4116657905313446), (4483,8295479824358343979,4114821341447591), + (4493,15778063092647631173,4105663047787569), (4507,8402743639522012307,4092909712382860), + (4513,662169851526910561,4087468219301917), (4517,3695882972483317293,4083848588379356), + (4519,2249204687898641943,4082041175859604), (4523,3597176270840553731,4078431146077725), + (4547,4819602366300186347,4056904348737530), (4549,1184095245003998477,4055120702068487), + (4561,12804733991967647537,4044451671499572), (4567,8667990536934683111,4039138181237037), + (4583,4512066355362951639,4025036891492374), (4591,9422264180537769231,4018023104706937), + (4597,13996572401370223197,4012778784796508), (4603,5570491910157783347,4007548136804160), + (4621,14482749945773264069,3991937691778738), (4637,16867413170698403893,3978163483655283), + (4639,13106373888110946783,3976448388383175), (4643,1326989558608440715,3973022630564193), + (4649,5773287293449644569,3967895047044429), (4651,16011504155142003843,3966188792455289), + (4657,2150865800305837777,3961078821926036), (4663,636913102266188679,3955982001653345), + (4673,5542313006524333505,3947516386413342), (4679,13912921529412482935,3942454386345277), + (4691,2355489170784911835,3932369233363792), (4703,18325151671777806751,3922335546185318), + (4721,2961794536723541649,3907380655308102), (4723,13908290418479719099,3905726037202953), + (4729,3237639581556127689,3900770580188105), (4733,18244075429755844309,3897473922186678), + (4751,1615206384900689007,3882707656011271), (4759,17136594988415618343,3876180725721696), + (4783,3089241480878392399,3856730937426207), (4787,11117371350042209403,3853508266912377), + (4789,7965727029532543901,3851898950450939), (4793,16872632175911261065,3848684346695086), + (4799,7976035414241991999,3843872488791321), (4801,15891633719821434177,3842271208854311), + (4813,13560062441883314693,3832691475942146), (4817,4702636853335131697,3829508838220791), + (4831,8923626764698659103,3818411110269002), (4861,4770120818895886933,3794845520203569), + (4871,11845907506171931319,3787054829338852), (4877,9005884281218462661,3782395750196750), + (4889,14832102874565810473,3773111898897433), (4903,17190123123144797335,3762338175343575), + (4909,5264593287281947813,3757739676860776), (4919,7211443149775049351,3750100441900701), + (4931,13205639136117363051,3740974259523332), (4933,8869993298771347341,3739457545856385), + (4937,15565958235988250361,3736427805085993), (4943,8564693030379004847,3731892387964707), + (4951,3968043312159295591,3725862264938305), (4957,9638302834558753013,3721352445775580), + (4967,16541533743568017495,3713860292673555), (4969,10357499691215465689,3712365480722389), + (4973,5515847262740016741,3709379463846682), (4987,7294361201795716019,3698966126671255), + (4993,964270018673781889,3694521144343991), (4999,13125638861809336887,3690086832108331), + (5003,9487002298951564323,3687136532822216), (5009,2938810495272553841,3682719918887912), + (5011,17154625301035025051,3681250064599790), (5021,14901412858587122357,3673918357639823), + (5023,8751461502617929823,3672455519352887), (5039,7526593731999769423,3660794616731405), + (5051,3031240859469199731,3652097421047228), (5059,14629044717082965227,3646322212632842), + (5077,14050336681708653949,3633394538843717), (5081,10953321564727753833,3630534161328390), + (5087,4587208817228736543,3626252029429831), (5099,15849222550876945603,3617717998374103), + (5101,7395332607476187621,3616299563558037), (5107,10818092520219327803,3612050924948022), + (5113,14341053724427042377,3607812257717494), (5119,4551325994353421311,3603583526803975), + (5147,12293050742728533523,3583979808375665), (5153,2233799398795800545,3579806728839423), + (5167,11445763789493482191,3570107233154548), (5171,5586463202364950267,3567345595379917), + (5179,3344563175364601075,3561835117534186), (5189,16850562133240176269,3554970914185691), + (5197,4678239116634440837,3549498571042823), (5209,4228337958151123945,3541321572990891), + (5227,12210777596142155843,3529126472873455), (5231,818131260772436623,3526427848157054), + (5233,5062014999015271569,3525080082879715), (5237,16544654747797167069,3522387640578489), + (5261,7296649765707959877,3506318964780374), (5273,10047230984201371561,3498339479178750), + (5279,6384201822820108127,3494363340350360), (5281,2997028292982919009,3493039968511560), + (5297,8566922866023314513,3482488969928176), (5303,12933244289280051463,3478548759892429), + (5309,6038885138464343701,3474617455963373), (5323,4168971091616116963,3465478879148891), + (5333,15983949815228171389,3458980700114298), (5347,6623854240045322443,3449924083356938), + (5351,13155069217954709207,3447345182902177), (5381,15004905930240978893,3428125640904952), + (5387,14803280978401037987,3424307420402738), (5393,17827633990761020401,3420497695848238), + (5399,7250229843380564647,3416696438916382), (5407,17075264303479989983,3411641219476521), + (5413,8267467416002100909,3407859610882976), (5417,6194319267136362265,3405343192488379), + (5419,9225074080042975619,3404086376399621), (5431,9948538647007047815,3396564918746004), + (5437,11023261264572803605,3392816640373285), (5441,6736570570568071873,3390322380758969), + (5443,1633534933589565291,3389076625704492), (5449,8693565568230157561,3385344847441650), + (5471,7279568717810075295,3371731689583175), (5477,14122183293968258157,3368037990452720), + (5479,17918155130549778007,3366808555157793), (5483,9891195983349641027,3364352375288993), + (5501,10026497869549456341,3353343769080085), (5503,305043378285947519,3352125036109313), + (5507,2599359615253061931,3349690225841574), (5519,8001722288903907695,3342406971137806), + (5521,12486050100244990833,3341196173466682), (5527,15569759562846943783,3337569038123674), + (5531,2498031334516082835,3335155319781151), (5557,15827618453022699677,3319550850046707), + (5563,1369495830027331443,3315970532753829), (5569,14359245027748411969,3312397930276450), + (5573,15080453256741560589,3310020468995074), (5581,13835884374224723717,3305275770240019), + (5591,16546310414890610151,3299363991005106), (5623,13912972010777557959,3280587599806073), + (5639,843990064021469111,3271279317912670), (5641,4133431042221037625,3270119495428036), + (5647,7993480210442229999,3266644957271038), (5651,5957407172981761051,3264332697524252), + (5653,3899497464723671357,3263177794747842), (5657,3759783616225404457,3260870439050654), + (5659,6816070305376687123,3259717984398224), (5669,14714442882574456237,3253967908574625), + (5683,2054687488766170363,3245951798998689), (5689,17999275154361350153,3242528401073923), + (5693,14694534406160691477,3240250144688134), (5701,11150233306087197837,3235703222892396), + (5711,16615312820024852655,3230037484452731), (5717,10486604554758797053,3226647555310399), + (5737,2205763715280591321,3215399001866751), (5741,2609084861148259173,3213158695995393), + (5743,346900289040681103,3212039713339639), (5749,2717758258902763997,3208687436721090), + (5779,4197520065223751579,3192030467850761), (5783,10344594679412082983,3189822596180105), + (5791,8043175407721743711,3185416003058116), (5801,10566890287353359769,3179924853251086), + (5807,10819633255563067471,3176639241210530), (5813,13007604327909074845,3173360411785575), + (5821,1191543681792611477,3168999153703753), (5827,819925641855289835,3165736068939342), + (5839,14295515830370906159,3159230017761526), (5843,14490938781161533787,3157067272584212), + (5849,649688712460962153,3153828701266806), (5851,1588986329370981715,3152750653513852), + (5857,16739703730880359713,3149520927729136), (5861,13656444725443737325,3147371450897381), + (5867,5499123126797001155,3144152731158948), (5869,2618186712114509541,3143081287052232), + (5879,15525512787330304711,3137735001481468), (5881,9798950601303968585,3136667926153639), + (5897,6043600059421206329,3128157380652798), (5903,9878054890224613359,3124977820381086), + (5923,2229928880090501259,3114425810182264), (5927,13031300394233489559,3112323953721874), + (5939,8684474899830258683,3106035371899234), (5953,167331459764877505,3098730736386620), + (5981,1761091935477036277,3084224055126158), (5987,4159529731001819723,3081133134075422), + (6007,5008596568040665671,3070874658516655), (6011,1224463630911680435,3068831155167118), + (6029,6296798690279359301,3059668945713974), (6037,9414347936243022781,3055614390211951), + (6043,12027167243159959187,3052580518568517), (6047,9465891658792911967,3050561282240706), + (6053,5250906994713622573,3047537431638782), (6067,12578569347772608379,3040505039345566), + (6073,2019938219828231817,3037501082448468), (6079,12930017519012403263,3034503055388970), + (6089,13023904216271532665,3029519473429060), (6091,3534288349042693603,3028524720687826), + (6101,4934451127404358013,3023560739831101), (6113,14047046239672495137,3017625400574112), + (6121,12365134934558126169,3013681436645899), (6131,13226535140764506427,3008765955587922), + (6133,12392073305671507037,3007784782929977), (6143,9690321199065720831,3002888502964276), + (6151,17867940365983012279,2998982941588286), (6163,5827650610337903131,2993143610856652), + (6173,16486422655865154101,2988294844274996), (6197,10207178542641609245,2976721651397378), + (6199,14244969169357577607,2975761263705364), (6203,16347211377266065651,2973842346237232), + (6211,13388813763368645739,2970011926213097), (6217,2222392039763302905,2967145580458348), + (6221,5610229832415764613,2965237754976619), (6229,9361078506501186813,2961429454761526), + (6247,17153375432076002135,2952896442085729), (6257,17739181571281823889,2948177093448865), + (6263,3572712847103574343,2945352718139797), (6269,15030462390893027541,2942533749195972), + (6271,15458083257430026111,2941595291613706), (6277,13198076730130571341,2938783507043102), + (6287,11343265880222860911,2934109125768975), (6299,12282210612023790995,2928519459233140), + (6301,3940536029711642037,2927589918062141), (6311,14059394548335120151,2922951049549921), + (6317,17115144374863334181,2920174778171529), (6323,9411544580387001979,2917403775693429), + (6329,17248827844558876041,2914638027130597), (6337,14927395235913299777,2910958509343467), + (6343,6293355537680509175,2908204961959569), (6353,3205604510841389105,2903627274312852), + (6359,12865436384164469479,2900887572528628), (6361,17086655570240005993,2899975487141888), + (6367,14680328603971461919,2897242669029299), (6373,10177114728254006509,2894514996659273), + (6379,9323138876569931715,2891792455511765), (6389,11153509525237125981,2887266250384966), + (6397,15969684020666483797,2883655475021033), (6421,14505156646653095485,2872877133423072), + (6427,10054293525782567187,2870195125830022), (6449,12242528242437103569,2860403794961940), + (6451,8564253371688126971,2859516985538606), (6469,15991550589791801741,2851560376211091), + (6473,5639750737196230905,2849798250225483), (6481,5610018912094048177,2846280523639801), + (6491,9128168535627034323,2841895559037059), (6521,8557184607111086281,2828821357722673), + (6529,14697497728815605377,2825355195850750), (6547,518436063779220635,2817587303147938), + (6551,13597821268805285415,2815866901802709), (6553,17436156385252092585,2815007488739440), + (6563,17465803393879499275,2810718280315336), (6569,10626043473118730905,2808151023551461), + (6571,18101446627192084739,2807296313150137), (6577,7505471665082371921,2804735300852904), + (6581,1345454665762131101,2803030553671106), (6599,7161775771608406007,2795384766435755), + (6607,3696608014770916655,2792000011156281), (6619,15353242650259241555,2786938219324603), + (6637,8357595213145189349,2779379851395141), (6653,1186713732684155733,2772695637112513), + (6659,12391092692852203691,2770197337995127), (6661,4536220806596043469,2769365571792456), + (6673,10526779774117484273,2764385444883793), (6679,13467034601498394023,2761902092185888), + (6689,17961376013166438881,2757773071267685), (6691,8973868175149393291,2756948748125773), + (6701,16605097784303240613,2752834513312871), (6703,14324228390818770127,2752013139446449), + (6709,9246743228481923101,2749551956134975), (6719,4530008590805292479,2745459752003207), + (6733,3843870776090078853,2739751087733484), (6737,5292794462591741617,2738124398650668), + (6761,3486901187132200409,2728404684766979), (6763,8150062293692760643,2727597822521004), + (6779,5891311538513228979,2721160063978396), (6781,6999479796734209749,2720357480269805), + (6791,11036536765054028599,2716351652732962), (6793,12073343758532705209,2715551902503982), + (6803,4238168600206971803,2711560204866904), (6823,627237963520535831,2703611911726447), + (6827,1680661317393780739,2702027841469100), (6829,6950281520230586661,2701236502227200), + (6833,3018214528670756433,2699655213480104), (6841,9284043245984795529,2696498183556432), + (6857,14225810509227958137,2690206223378963), (6863,14941782064075680815,2687854301866465), + (6869,9963229074605100669,2685506489111886), (6871,15958004187764455655,2684724796057277), + (6883,2355758832019569355,2680044177496665), (6899,17246194995713379899,2673828681505950), + (6907,17672231871396569139,2670731732113732), (6911,16193951135175206143,2669185946130741), + (6917,370695016082930125,2666870619301655), (6947,6718045560167722123,2655353976350878), + (6949,5802933162344089773,2654589735747525), (6959,7962928466363485135,2650775121958550), + (6961,12534563923092397521,2650013514395855), (6967,977012855346465415,2647731315302074), + (6971,3191331710356293107,2646212031804554), (6977,14766384642635494593,2643936372898029), + (6983,2826581148341575287,2641664624618294), (6991,16045580133346843567,2638641692706272), + (6997,9506782782592059901,2636379030114270), (7001,5401489123140205801,2634872742995222), + (7013,5523764801766727277,2630364191317489), (7019,1952689962496964931,2628115696496588), + (7027,4502087104939786683,2625123676349729), (7039,9670192588718318719,2620648398026644), + (7043,12207904888195402539,2619160027503840), (7057,13242341714242962801,2613964017813454), + (7069,10281535104033899189,2609526676150735), (7079,16080641005630970903,2605840383346454), + (7103,17083300368416363583,2597035629129881), (7109,12639483806870055693,2594843729597629), + (7121,11885081001289063729,2590471011614878), (7127,16831651004817344487,2588290174506742), + (7129,16953719619995087977,2587564044565794), (7151,7261583634106053391,2579603422417780), + (7159,5158595004269663687,2576720781353478), (7177,17238722656035942969,2570258335475763), + (7187,10628630472969424411,2566682075095248), (7193,9324671409983029289,2564541091854518), + (7207,6974799167595189143,2559559327557867), (7211,12552790621230449283,2558139519305165), + (7213,5431981756905460645,2557430205699369), (7219,9740821223019921147,2555304623037754), + (7229,13549897777202617109,2551769826215182), (7237,779978400795235981,2548949022206653), + (7243,1319261829377543523,2546837508450856), (7247,6600304592676813487,2545431775039264), + (7253,4702609925863637245,2543326082132848), (7283,11559925848195852475,2532849659990327), + (7297,1266523061659378561,2527990143032691), (7307,7389300657417251619,2524530460340707), + (7309,9509827838245668421,2523839659831652), (7321,7339894206626953129,2519702782913475), + (7331,7936302115465819915,2516265730965700), (7333,4512949525192272685,2515579445480642), + (7349,8313459841083961757,2510102609022935), (7351,7613579311608594695,2509419680820235), + (7369,10356110765766917497,2503290008645616), (7393,13329163646930396961,2495163543042006), + (7411,12017390418009676859,2489103234881871), (7417,16529197939041887561,2487089668829655), + (7433,16411720511158518073,2481736051891504), (7451,4867306247337669907,2475740715838082), + (7457,13959363927577175777,2473748702388299), (7459,7204097799532903051,2473085410069654), + (7477,16714817587184995613,2467131747185977), (7481,8879391178910318857,2465812601752379), + (7487,8327767459481539263,2463836526473828), (7489,2943498353329271489,2463178538350854), + (7499,7741285984793166947,2459893862342919), (7507,6275873766385266395,2457272422233855), + (7517,15651634122937278197,2454003468632373), (7523,10828236319221238859,2452046267939592), + (7529,4687026353168597721,2450092186706010), (7537,14956621073960338321,2447491584676867), + (7541,1223096676416228061,2446193352832456), (7547,11989039311189260723,2444248585359686), + (7549,8528167547654833109,2443601016520009), (7559,8011729169729919031,2440368312436770), + (7561,7380161463162464441,2439722797739657), (7573,10532645104281011645,2435856869630206), + (7577,8104686686205503145,2434570948094173), (7583,11637771811766648415,2432644609482995), + (7589,3417594171516092973,2430721316867775), (7591,14242704125413210647,2430080894968983), + (7603,2938183226787092859,2426245439130547), (7607,6697766153751252999,2424969642922249), + (7621,10459044894698723597,2420514902730553), (7639,12602900552518673895,2414811372392924), + (7643,8312257829367486035,2413547569502754), (7649,8303325904795657761,2411654343536351), + (7669,1820861294014621277,2405364985488271), (7673,17468270877045953609,2404111048313508), + (7681,13079152223072805377,2401607092007492), (7687,12399418060212989879,2399732545038318), + (7691,16966879154521046435,2398484471942471), (7699,12504683377151597595,2395992216354013), + (7703,16902131594475141543,2394748029820790), (7717,12155201971596873133,2390403534237339), + (7723,5099546626617880707,2388546429329218), (7727,11158286760776296655,2387309961655176), + (7741,15213023403508820245,2382992387767672), (7753,6999912429363278841,2379304020857674), + (7757,9407673012194790021,2378077101161473), (7759,4426838183431780527,2377464115699130), + (7789,8521168978971237221,2368307109219354), (7793,10912291823405752977,2367091501823373), + (7817,15223224513176451001,2359823982820717), (7823,5647443698905071727,2358014070524038), + (7829,13225389511525317821,2356206932393607), (7841,3761808924099167585,2352600953157703), + (7853,14765851680547337509,2349005994360060), (7867,16228538926419703411,2344825737092862), + (7873,17809437533883691329,2343038749359780), (7877,3187256402731839501,2341848936614136), + (7879,15749618908978823927,2341254483273201), (7883,13069271299209418467,2340066481505715), + (7901,7641588830939294069,2334735359284843), (7907,12420698804657854155,2332963712369995), + (7919,12818844884155027471,2329428472497733), (7927,7937661667140567751,2327077592242910), +]; + +pub const NEXT_PRIME: u64 = 7933; From 1c93a793e95658eab54e1754ce39d9b5d1240519 Mon Sep 17 00:00:00 2001 From: kwantam Date: Thu, 30 Apr 2015 01:46:10 -0400 Subject: [PATCH 04/11] fix `touch` --- src/touch/touch.rs | 89 ++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/src/touch/touch.rs b/src/touch/touch.rs index 8119f6114..48687828a 100644 --- a/src/touch/touch.rs +++ b/src/touch/touch.rs @@ -1,5 +1,5 @@ #![crate_name = "touch"] -#![feature(collections, core, old_io, old_path, rustc_private)] +#![feature(rustc_private, path_ext, fs_time)] /* * This file is part of the uutils coreutils package. @@ -10,11 +10,19 @@ * that was distributed with this source code. */ +extern crate libc; extern crate getopts; extern crate time; -use std::old_io::File; -use std::old_io::fs::PathExtensions; +use libc::types::os::arch::c95::c_char; +use libc::types::os::arch::posix01::stat as stat_t; +use libc::funcs::posix88::stat_::stat as c_stat; +use libc::funcs::posix01::stat_::lstat as c_lstat; + +use std::fs::{set_file_times, File, PathExt}; +use std::io::{Error, Write}; +use std::mem::uninitialized; +use std::path::Path; #[path = "../common/util.rs"] #[macro_use] @@ -40,7 +48,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("V", "version", "output version information and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(e) => panic!("Invalid options\n{}", e) }; @@ -71,14 +79,12 @@ pub fn uumain(args: Vec) -> i32 { let (mut atime, mut mtime) = if matches.opt_present("reference") { - let path = Path::new(matches.opt_str("reference").unwrap().to_string()); - let stat = stat(&path, !matches.opt_present("no-dereference")); - (stat.accessed, stat.modified) + stat(&matches.opt_str("reference").unwrap()[..], !matches.opt_present("no-dereference")) } else if matches.opts_present(&["date".to_string(), "t".to_string()]) { let timestamp = if matches.opt_present("date") { - parse_date(matches.opt_str("date").unwrap().as_slice()) + parse_date(matches.opt_str("date").unwrap().as_ref()) } else { - parse_timestamp(matches.opt_str("t").unwrap().as_slice()) + parse_timestamp(matches.opt_str("t").unwrap().as_ref()) }; (timestamp, timestamp) } else { @@ -88,17 +94,20 @@ pub fn uumain(args: Vec) -> i32 { }; for filename in matches.free.iter() { - let path = Path::new(filename.to_string()); + let path = &filename[..]; - if !path.exists() { + if ! Path::new(path).exists() { // no-dereference included here for compatibility if matches.opts_present(&["no-create".to_string(), "no-dereference".to_string()]) { continue; } - match File::create(&path) { - Ok(fd) => fd, - Err(e) => panic!("Unable to create file: {}\n{}", filename, e.desc) + match File::create(path) { + Err(e) => { + show_warning!("cannot touch '{}': {}", path, e); + continue; + }, + _ => (), }; // Minor optimization: if no reference time was specified, we're done. @@ -110,44 +119,62 @@ pub fn uumain(args: Vec) -> i32 { // If changing "only" atime or mtime, grab the existing value of the other. // Note that "-a" and "-m" may be passed together; this is not an xor. if matches.opts_present(&["a".to_string(), "m".to_string(), "time".to_string()]) { - let stat = stat(&path, !matches.opt_present("no-dereference")); + let st = stat(path, !matches.opt_present("no-dereference")); let time = matches.opt_strs("time"); if !(matches.opt_present("a") || time.contains(&"access".to_string()) || time.contains(&"atime".to_string()) || time.contains(&"use".to_string())) { - atime = stat.accessed; + atime = st.0; } if !(matches.opt_present("m") || time.contains(&"modify".to_string()) || time.contains(&"mtime".to_string())) { - mtime = stat.modified; + mtime = st.1; } } - match std::old_io::fs::change_file_times(&path, atime, mtime) { - Ok(t) => t, - Err(e) => panic!("Unable to modify times\n{}", e.desc) - } + // this follows symlinks and thus does not work correctly for the -h flag + // need to use lutimes() c function on supported platforms + match set_file_times(path, atime, mtime) { + Err(e) => show_warning!("cannot touch '{}': {}", path, e), + _ => (), + }; } 0 } -fn stat(path: &Path, follow: bool) -> std::old_io::FileStat { - if follow { - match std::old_io::fs::stat(path) { - Ok(stat) => stat, - Err(e) => panic!("Unable to open file\n{}", e.desc) - } +fn stat(path: &str, follow: bool) -> (u64, u64) { + let stat_fn = if follow { + c_stat } else { - match std::old_io::fs::lstat(path) { - Ok(stat) => stat, - Err(e) => panic!("Unable to open file\n{}", e.desc) - } + c_lstat + }; + let mut st: stat_t = unsafe { uninitialized() }; + let result = unsafe { stat_fn(path.as_ptr() as *const c_char, &mut st as *mut stat_t) }; + + if result < 0 { + crash!(1, "failed to get attributes of '{}': {}", path, Error::last_os_error()); } + + // set_file_times expects milliseconds + let atime = if st.st_atime_nsec == 0 { + st.st_atime * 1000 + } else { + st.st_atime_nsec / 1000 + } as u64; + + // set_file_times expects milliseconds + let mtime = if st.st_mtime_nsec == 0 { + st.st_mtime * 1000 + } else { + st.st_mtime_nsec / 1000 + } as u64; + + (atime, mtime) } fn parse_date(str: &str) -> u64 { From cab4f8d570741b2985cef07e5acdd58f5efe8f4e Mon Sep 17 00:00:00 2001 From: kwantam Date: Thu, 30 Apr 2015 02:16:53 -0400 Subject: [PATCH 05/11] fix `test` --- mkuutils.rs | 6 +++++- src/test/test.rs | 16 ++++++++-------- test/test.rs | 14 ++++++++++---- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/mkuutils.rs b/mkuutils.rs index 48f167360..2d9dfa01a 100644 --- a/mkuutils.rs +++ b/mkuutils.rs @@ -39,7 +39,11 @@ fn main() { util_map.push_str("map.insert(\"false\", uufalse as fn(Vec) -> i32);\n"); }, _ => { - crates.push_str(&(format!("extern crate {0} as uu{0};\n", prog))[..]); + if prog == "test" { + crates.push_str(&(format!("extern crate uu{0} as uu{0};\n", prog))[..]); + } else { + crates.push_str(&(format!("extern crate {0} as uu{0};\n", prog))[..]); + } util_map.push_str(&(format!("map.insert(\"{prog}\", uu{prog}::uumain as fn(Vec) -> i32);\n", prog = prog))[..]); } } diff --git a/src/test/test.rs b/src/test/test.rs index 5251a997e..f9ef059e7 100644 --- a/src/test/test.rs +++ b/src/test/test.rs @@ -1,5 +1,5 @@ #![crate_name = "test"] -#![feature(core, os, std_misc)] +#![feature(convert)] /* * This file is part of the uutils coreutils package. @@ -13,16 +13,16 @@ extern crate libc; use std::collections::HashMap; -use std::ffi::CString; -use std::os::{args_as_bytes}; +use std::ffi::{CString, OsString}; +use std::env::{args_os}; use std::str::{from_utf8}; static NAME: &'static str = "test"; // TODO: decide how to handle non-UTF8 input for all the utils pub fn uumain(_: Vec) -> i32 { - let args = args_as_bytes(); - let args: Vec<&[u8]> = args.iter().map(|a| a.as_slice()).collect(); + let args = args_os().collect::>(); + let args = args.iter().map(|a| a.to_bytes().unwrap()).collect::>(); if args.len() == 0 { return 2; } @@ -30,7 +30,7 @@ pub fn uumain(_: Vec) -> i32 { if !args[0].ends_with(NAME.as_bytes()) { &args[1..] } else { - args.as_slice() + &args[..] }; let args = match args[0] { b"[" => match args[args.len() - 1] { @@ -83,6 +83,7 @@ fn two(args: &[&[u8]], error: &mut bool) -> bool { fn three(args: &[&[u8]], error: &mut bool) -> bool { match args[1] { b"=" => args[0] == args[2], + b"==" => args[0] == args[2], b"!=" => args[0] != args[2], b"-eq" => integers(args[0], args[2], IntegerCondition::Equal), b"-ne" => integers(args[0], args[2], IntegerCondition::Unequal), @@ -191,6 +192,7 @@ fn dispatch_four(args: &mut &[&[u8]], error: &mut bool) -> (bool, usize) { } } +#[derive(Clone, Copy)] enum Precedence { Unknown = 0, Paren, // FIXME: this is useless (parentheses have not been implemented) @@ -201,8 +203,6 @@ enum Precedence { UnOp } -impl Copy for Precedence {} - fn parse_expr(mut args: &[&[u8]], error: &mut bool) -> bool { if args.len() == 0 { false diff --git a/test/test.rs b/test/test.rs index 480d0aa3f..b792538ea 100644 --- a/test/test.rs +++ b/test/test.rs @@ -1,6 +1,13 @@ -#![allow(unstable)] +/* + * This file is part of the uutils coreutils package. + * + * (c) mahkoh (ju.orth [at] gmail [dot] com) + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -use std::old_io::process::Command; +use std::process::Command; static EXE: &'static str = "./test"; @@ -26,6 +33,5 @@ fn test_op_prec_and_or_2() { #[test] fn test_or_as_filename() { let status = Command::new(EXE).arg("x").arg("-a").arg("-z").arg("-o").status(); - assert!(status.unwrap().matches_exit_status(1)); + assert_eq!(status.unwrap().code(), Some(1)); } - From 9a806346a91535ad52caf66eb65b66b43c23b571 Mon Sep 17 00:00:00 2001 From: kwantam Date: Thu, 30 Apr 2015 14:23:12 -0400 Subject: [PATCH 06/11] add test for `factor` Add a test for `factor`. This commit also pulls factor's Sieve implementation into its own module so that the factor test can use it. Finally, slight refactoring for clarity in gen_table.rs. --- Makefile | 1 + src/factor/gen_table.rs | 97 +--- src/factor/prime_table.rs | 1002 ++++++++++++++++++------------------- src/factor/sieve.rs | 53 ++ test/factor.rs | 89 ++++ 5 files changed, 670 insertions(+), 572 deletions(-) create mode 100644 src/factor/sieve.rs create mode 100644 test/factor.rs diff --git a/Makefile b/Makefile index b6085bd85..6218c782f 100644 --- a/Makefile +++ b/Makefile @@ -161,6 +161,7 @@ TEST_PROGS := \ cat \ cp \ env \ + factor \ mkdir \ mv \ nl \ diff --git a/src/factor/gen_table.rs b/src/factor/gen_table.rs index 0cb9ea21a..fefa87b0b 100644 --- a/src/factor/gen_table.rs +++ b/src/factor/gen_table.rs @@ -13,8 +13,8 @@ //! 2 has no multiplicative inverse mode 2^64 because 2 | 2^64, //! and in any case divisibility by two is trivial by checking the LSB. +use sieve::Sieve; use std::env::args; -use std::iter::repeat; use std::num::Wrapping; use std::u64::MAX as MAX_U64; @@ -24,48 +24,7 @@ use numeric::is_prime; #[cfg(test)] mod numeric; -// A lazy Sieve of Eratosthenes -// Not particularly efficient, but fine for generating a few thousand primes. -struct Sieve { - inner: Box>, - filts: Vec, -} - -impl Iterator for Sieve { - type Item = u64; - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.inner.size_hint() - } - - #[inline] - fn next(&mut self) -> Option { - while let Some(n) = self.inner.next() { - if self.filts.iter().all(|&x| n % x != 0) { - self.filts.push(n); - return Some(n); - } - } - None - } -} - -impl Sieve { - #[inline] - pub fn new() -> Sieve { - fn next(s: &mut u64, t: u64) -> Option { - let ret = Some(*s); - *s = *s + t; - ret - } - let next = next; - - let odds_by_3 = Box::new(repeat(2).scan(3, next)) as Box>; - - Sieve { inner: odds_by_3, filts: Vec::new() } - } -} +mod sieve; // extended Euclid algorithm // precondition: a does not divide 2^64 @@ -105,38 +64,34 @@ fn inv_mod_u64(a: u64) -> Option { #[cfg_attr(test, allow(dead_code))] fn main() { - // By default, we print the multiplicative inverses mod 2^64 of the first 10k primes - let n = args().skip(1).next().unwrap_or("10000".to_string()).parse::().ok().unwrap_or(10000); + // By default, we print the multiplicative inverses mod 2^64 of the first 1k primes + let n = args().skip(1).next().unwrap_or("1000".to_string()).parse::().ok().unwrap_or(1000); print!("{}", PREAMBLE); + let mut cols = 3; - let m = n; - Sieve::new() - .scan((0, 3), move |st, x| { - let (count, mut cols) = *st; - if count < m { - // format the table - let outstr = format!("({}, {}, {}),", x, inv_mod_u64(x).unwrap(), MAX_U64 / x); - if cols + outstr.len() > MAX_WIDTH { - print!("\n {}", outstr); - cols = 4 + outstr.len(); - } else { - print!(" {}", outstr); - cols += 1 + outstr.len(); - } + // we want a total of n + 1 values + let mut primes = Sieve::new().take(n + 1); - *st = (count + 1, cols); - Some(1) - } else if count == m { - // now we're done formatting the table, print NEXT_PRIME - print!("\n];\n\npub const NEXT_PRIME: u64 = {};\n", x); + // in each iteration of the for loop, we use the value yielded + // by the previous iteration. This leaves one value left at the + // end, which we call NEXT_PRIME. + let mut x = primes.next().unwrap(); + for next in primes { + // format the table + let outstr = format!("({}, {}, {}),", x, inv_mod_u64(x).unwrap(), MAX_U64 / x); + if cols + outstr.len() > MAX_WIDTH { + print!("\n {}", outstr); + cols = 4 + outstr.len(); + } else { + print!(" {}", outstr); + cols += 1 + outstr.len(); + } - *st = (count + 1, cols); - Some(1) - } else { - None - } - }).take(m + 1).count(); + x = next; + } + + print!("\n];\n\npub const NEXT_PRIME: u64 = {};\n", x); } #[test] @@ -150,7 +105,7 @@ fn test_generator_and_inverter() { })); } -const MAX_WIDTH: usize = 100; +const MAX_WIDTH: usize = 102; const PREAMBLE: &'static str = r##"/* * This file is part of the uutils coreutils package. diff --git a/src/factor/prime_table.rs b/src/factor/prime_table.rs index 15e035be3..968f7e9fe 100644 --- a/src/factor/prime_table.rs +++ b/src/factor/prime_table.rs @@ -11,507 +11,507 @@ // Please do not edit by hand. Instead, modify and // re-run src/factor/gen_tables.rs. -pub const P_INVS_U64: &'static [(u64,u64,u64)] = &[ - (3,12297829382473034411,6148914691236517205), (5,14757395258967641293,3689348814741910323), - (7,7905747460161236407,2635249153387078802), (11,3353953467947191203,1676976733973595601), - (13,5675921253449092805,1418980313362273201), (17,17361641481138401521,1085102592571150095), - (19,9708812670373448219,970881267037344821), (23,15238614669586151335,802032351030850070), - (29,3816567739388183093,636094623231363848), (31,17256631552825064415,595056260442243600), - (37,1495681951922396077,498560650640798692), (41,10348173504763894809,449920587163647600), - (43,9437869060967677571,428994048225803525), (47,5887258746928580303,392483916461905353), - (53,2436362424829563421,348051774975651917), (59,14694863923124558067,312656679215416129), - (61,5745707170499696405,302405640552615600), (67,17345445920055250027,275324538413575397), - (71,1818693077689674103,259813296812810586), (73,9097024474706080249,252695124297391118), - (79,11208148297950107311,233503089540627235), (83,11779246215742243803,222249928598910260), - (89,17617676924329347049,207266787345051141), (97,11790702397628785569,190172619316593315), - (101,4200743699953660269,182641030432767837), (103,15760325033848937303,179094602657374287), - (107,8619973866219416643,172399477324388332), (109,12015769075535579493,169236184162472950), - (113,10447713457676206225,163245522776190722), (127,9150747060186627967,145249953336295682), - (131,281629680514649643,140814840257324821), (137,16292379802327414201,134647766961383588), - (139,4246732448623781667,132710389019493177), (149,16094474695182830269,123803651501406386), - (151,8062815290495565607,122163868037811600), (157,6579730370240349621,117495185182863386), - (163,2263404180823257867,113170209041162893), (167,10162278172342986519,110459545351554201), - (173,9809829218388894501,106628578460748853), (179,17107036403551874683,103054436165975148), - (181,3770881385233444253,101915713114417412), (191,2124755861893246783,96579811904238490), - (193,8124213711219232577,95578984837873324), (197,14513935692512591373,93638294790403815), - (199,2780916192016515319,92697206400550510), (211,13900627050804827995,87425327363552377), - (223,7527595115280579359,82720825442643729), (227,1950316554048586955,81263189752024456), - (229,2094390156840385773,80553467570784068), (233,7204522363551799129,79170575423646144), - (239,7255204782128442895,77183029597111094), (241,17298606475760824337,76542506529915151), - (251,2939720171109091891,73493004277727297), (257,18374966859414961921,71777214294589695), - (263,15430736487513693367,70139711306880424), (269,10354863773718001093,68575256779589411), - (271,15383631589145234927,68069166323651481), (277,17181443938689762877,66594743948409933), - (281,14245350405676059433,65646776063023315), (283,5149444458738708755,65182841249857072), - (293,2707201348701401773,62958170900032599), (307,17305088903023944187,60087114246610917), - (311,9134400602415662215,59314289626075728), (313,6365010734698503433,58935284580541698), - (317,17050145153302519317,58191621683626345), (331,3455281367280943203,55730344633563600), - (337,9196002980365592497,54738112978366622), (347,9941040754419844819,53160645745560667), - (349,15751088062938241781,52856000211202153), (353,8779186981255537313,52257065364616293), - (359,5600822016808749655,51383688227603207), (367,9751139919072624015,50263607830271257), - (373,3511310534137743069,49455077945602015), (379,17181268226964305331,48672147951740241), - (383,14834457375202459263,48163822646761231), (389,12661389891209383757,47420935922132523), - (397,185861401246443845,46465350311610961), (401,3220129888178724721,46001855545410353), - (409,2074694932495450793,45102063749901104), (419,1849076971589024267,44025642180691053), - (421,14897608040525528621,43816494236839790), (431,8046375605237577039,42799870240625409), - (433,7540585914657253201,42602180308798040), (439,15379290047785184263,42019918163347497), - (443,15615189678648040307,41640505809728107), (449,205420312624827969,41084062524965593), - (457,686202733595322489,40364866682077793), (461,3041111821262312197,40014629227135686), - (463,8127723090792113455,39841779856824085), (467,15247201739725667931,39500522641776341), - (479,8010277176057592351,38510947961815347), (487,2386334448960373207,37878324586672590), - (491,1051952818867347139,37569743530976683), (499,12494988971771199291,36967422993405915), - (503,17969989256695189447,36673447462643243), (509,5436172123882971989,36241147492553146), - (521,1805727346946616377,35406418567580713), (523,7195288319381928355,35271021173440825), - (541,13911777416032342069,34097493666745936), (547,13219604528142859659,33723480939139948), - (557,5133295029488295333,33118032448311582), (563,18151858289227516155,32765087164670606), - (569,6386658317259721737,32419585366800617), (571,1873749835858413299,32306031652731263), - (577,8184343991108570561,31970093715267853), (587,8107768264083584867,31425458387920871), - (593,13407330009728190129,31107494222107169), (599,16999336775772408167,30795899956109435), - (601,10926856722530117097,30693417759916059), (607,7810235958720518559,30390023185682951), - (613,10111102787547160429,30092567820080834), (617,5112468778937331161,29897478239399597), - (619,10400506755613301315,29800878955912038), (631,14909412801254946631,29234142747558718), - (641,18417966001831689601,28778071877862015), (643,12450835035754191915,28688559990217032), - (647,16650538700226241335,28511196404496988), (653,18023005695293558853,28249225227732850), - (659,13744083976011213723,27992024391061535), (661,3544230707051608253,27907328401981167), - (673,7016889276180750689,27409723735081057), (677,7711120491668837677,27247775588935822), - (683,18338710433453565955,27008410063996415), (691,16604739238563445883,26695722248494285), - (701,4578792394900801685,26314898821268975), (709,17796294705807240205,26017974716092456), - (719,7799457855921701935,25656111368163493), (727,3501582781529460967,25373788271952615), - (733,8027982755134170485,25166090141486427), (739,12755461734324196043,24961764646426998), - (743,8416482154761154775,24827380987496031), (751,73688724661955599,24562908220651866), - (757,11233750354002778461,24368222026036395), (761,8193166224591101769,24240136759145271), - (769,8635666926574042369,23987963684927895), (773,11955781087876436429,23863834506739394), - (787,1757948926973591323,23439319026314550), (797,3332912354597459765,23145224684704581), - (809,12062209660064712985,22801908620160137), (811,2229076349227541379,22745677032934095), - (821,4044353146489304861,22468628591607249), (823,5536264624794968711,22414026821032261), - (827,9502192231439261171,22305615566758829), (829,9813044796750195733,22251802260204525), - (839,17941052639030982263,21986584116459537), (853,13018686907823153661,21625725760503577), - (857,12247604875076703465,21524788884141833), (859,858986918449804499,21474672961245112), - (863,13637338028999645343,21375137976488472), (877,4964004106494246501,21033915705484095), - (881,14447506709261737361,20938415520669184), (883,17047047751015848379,20890989890950794), - (887,15763959422628906567,20796780240935232), (907,11979197639928253475,20338196332645591), - (911,16462352285319281519,20248895799900715), (919,16098246732442938407,20072626848432591), - (929,13264181960428396641,19856559821000593), (937,11792529028977610905,19687026759561954), - (941,1725094026021722149,19603341204792297), (947,18271431828024877947,19479138409408185), - (953,18137040080866579081,19356499552685783), (967,9614435380713147895,19076260676018150), - (971,10828675717831559651,18997676697950104), (977,12064963626510136625,18881007240234955), - (983,9326583728009813991,18765762028188760), (991,13160290676198438943,18614272526447579), - (997,11785933776281829869,18502250826188115), (1009,6965519813759503633,18282204235589248), - (1013,7775675932353384541,18210013893099261), (1019,10372899268140896051,18102791043875909), - (1021,7497942008412795221,18067330140753723), (1031,13544311604071901623,17892089305246897), - (1033,15464550210873641529,17857448280454551), (1039,1881958490676816623,17754325383743553), - (1049,8370495880920635433,17585075380085368), (1051,15691141010367591955,17551611868420125), - (1061,10466484384894580653,17386186685871396), (1063,5917535022704569239,17353475139896097), - (1069,13511506650808773541,17256074905247475), (1087,4836542834413267903,16970325734783396), - (1091,12613447368457676907,16908106392034419), (1093,12235946434985750157,16877167496532069), - (1097,14007418243755748857,16815628143764404), (1103,13546566364192871087,16724156005176384), - (1109,14687533829653321981,16633673646266502), (1117,17043007953507839989,16514542590608372), - (1123,10923494932339137867,16426308168931034), (1129,8610659102608444377,16339011579902171), - (1151,2852754513571068799,16026710750399262), (1153,16894849732729650049,15998910731751562), - (1163,14877941479913636643,15861344861315177), (1171,10554499171123313051,15752983837497482), - (1181,9918444103984390581,15619597014148646), (1187,6884505159775342347,15540643701524474), - (1193,17503532515875282841,15462484554660143), (1201,10275496907003905105,15359487155461741), - (1213,12439766407497455253,15207538395473661), (1217,6745111842892974913,15157554703130280), - (1223,5399782811437464823,15083192210719175), (1229,11572367518982965253,15009555796346258), - (1231,1168843247562424879,14985169840543908), (1237,12988774525627339901,14912485104049758), - (1249,2171073962238033697,14769210627469616), (1259,2754557494723904451,14651901567680342), - (1277,8710561218830743637,14445375155606540), (1279,10802667170608642815,14422786609624356), - (1283,17756608675784330667,14377820790108769), (1289,715544766241642809,14310895324832856), - (1291,10173572254439349923,14288725076459761), (1297,9401154844041645041,14222624574949538), - (1301,4069343235322552893,14178896290322483), (1303,17455744775812645543,14157132827098658), - (1307,11545093077501463827,14113805718216948), (1319,7286393982109686423,13985401117293064), - (1321,10375420777264342809,13964227156479600), (1327,17848997280062595535,13901088224347815), - (1361,8864195903163884465,13553816365694012), (1367,11915490136858474087,13494326315808011), - (1373,7241656996161287925,13435356208091443), (1381,10365440551193781357,13357526483497140), - (1399,11511084757933122631,13185664098434275), (1409,11062809611273648769,13092082380205501), - (1423,11991031811792927087,12963277634370731), (1427,10910337770294927515,12926940486131430), - (1429,4001742941112638909,12908848197137544), (1433,6539390083352723113,12872815124710084), - (1439,3589359513994909279,12819141121410390), (1447,15973580044476895767,12748268191920906), - (1451,6496406768894266627,12713124792356686), (1453,16301183338364118565,12695625652931556), - (1459,12921571242858918267,12643416088903051), (1471,15612641993044453951,12540274693208396), - (1481,7535638193514030201,12455600319857901), (1483,10846635760131307491,12438802477214802), - (1487,7517637463798243631,12405342349502052), (1489,9155234298503263025,12388679700275051), - (1493,17211195240909179773,12355488328003718), (1499,11419998999601376851,12306033404742862), - (1511,5310611298519956951,12208301835678061), (1523,3355054568888736571,12112110356999048), - (1531,13325995392242171187,12048820426982071), (1543,7651274275550300087,11955116055547343), - (1549,15826806245293734085,11908808310980988), (1553,14028077753413380849,11878135269613362), - (1559,9773579605442007463,11832420829832938), (1567,5579934072072959455,11772012810280505), - (1571,4004035473669609867,11742039512227594), (1579,17874299197451307139,11682548495066213), - (1583,11163601277709254863,11653028473600474), (1597,8663154699613126933,11550872932817502), - (1601,13918592655241185729,11522013787451312), (1607,1503748272343466871,11478994445369976), - (1609,4574425659049167865,11464725962529242), (1613,2904818967589724805,11436295147991042), - (1619,3999263230310100443,11393912337065813), (1621,9707015851248764669,11379854456329149), - (1627,10045368930120874451,11337888182980670), (1637,13127951646836669293,11268628023035767), - (1657,2237655738573095881,11132615614791521), (1663,5291098570751326591,11092449833860223), - (1667,12747839935760889899,11065833277570216), (1669,12312566146262696525,11052572842246585), - (1693,14633182097455361973,10895891360726256), (1697,3782832609104846177,10870208646853006), - (1699,15080946155610692875,10857412639028576), (1709,5137887758388383013,10793881845353745), - (1721,4062356771607158665,10718619450150814), (1723,2141235527998787187,10706177639993935), - (1733,18372233278258907149,10644399350092066), (1741,3401151549489239557,10595487693112895), - (1747,8806287668845887835,10559097924275644), (1753,5387754116223211881,10522957258248460), - (1759,4184338195230307615,10487063145940620), (1777,7816768873102584337,10380835156842741), - (1783,6114428349726497479,10345902453005917), (1787,17001559870956704819,10322744305377477), - (1789,18085851931406681685,10311204065796283), (1801,15916846357881534265,10242500873797641), - (1811,13751024019606788891,10185943718227251), (1823,16463440816196072671,10118894170987137), - (1831,11374316799136037015,10074682727312698), (1847,10307005892836089479,9987408810887683), - (1861,10526836220461872013,9912275160510237), (1867,12903828473628641891,9880419964493600), - (1871,5176130752911552431,9859296672212480), (1873,10567728986166763953,9848768859428484), - (1877,8451891264459357693,9827780540069020), (1879,13538084128603231335,9817319890212640), - (1889,13896091485912489121,9765348900852065), (1901,9383483176894863973,9703705456975040), - (1907,2843913349591299515,9673174658473807), (1913,12053544219622027977,9642835375697622), - (1931,10661090826649331747,9552948769399042), (1933,6680145293117788997,9543064704453984), - (1949,13790100623599187637,9464722459573910), (1951,7043989920509285471,9455020027529242), - (1973,17128451669050125981,9349591522407274), (1979,736378363730699635,9321245110515185), - (1987,11864589293508206827,9283716192103448), (1993,11727057070441546361,9255767222132238), - (1997,13994400236189269253,9237227878672784), (1999,2768395808960913199,9227986029869710), - (2003,16319336244939253851,9209557700304319), (2011,15043590393278798931,9172920971511462), - (2017,493864243916864545,9145634146608602), (2027,11384744369122175171,9100515083231155), - (2029,5309462069515218405,9091544639580853), (2039,9698337247188150727,9046956387302379), - (2053,11797649765601871053,8985262578523892), (2063,3818109413220542191,8941708227682768), - (2069,3798121302755084093,8915777705997849), (2081,15698790847928695777,8864365244454373), - (2083,13345772116697212811,8855854092035310), (2087,12993154666196952983,8838880725304049), - (2089,7205621428505023513,8830418417285568), (2099,9913257415504704251,8788348772610553), - (2111,6859637185154901951,8738391318668664), (2113,34920480972474305,8730120243118576), - (2129,5588609641870672049,8664511072667708), (2131,16317274790681607131,8656379199300587), - (2137,13327923654566002665,8632074905806996), (2141,15749952436590873589,8615947722423891), - (2143,11310789413371138975,8607906707283971), (2153,15473673849103321049,8567925719326312), - (2161,6700922766248032401,8536207345538894), (2179,4893170295825663531,8465692553331597), - (2203,10433337773872946579,8373465308084226), (2207,10364278500860826463,8358289113597440), - (2213,8552354007964753709,8335627688074808), (2221,17059708386942556965,8305602914772423), - (2237,16393440866577822357,8246197619002928), (2239,15110017253766555455,8238831654180237), - (2243,14104398611864414187,8224139132282457), (2251,6883725020842302691,8194910739097979), - (2267,13865572078341894995,8137072815928342), (2269,4089339915855400821,8129900429135985), - (2273,15021963607759076129,8115593521209657), (2281,16036779262676914009,8087130238364555), - (2287,14583171528319575567,8065913455928968), (2293,13072812524979512157,8044807707679699), - (2297,4946971854333950281,8030798464827841), (2309,9770622781354171341,7989061963494825), - (2311,191571552474698935,7982148019779122), (2333,13362622153694445877,7906877014020382), - (2339,9984428387052711563,7886594302569282), (2341,12907204952044530349,7879856503079688), - (2347,10532014085543587203,7859712004137005), (2351,17214868778272546255,7846339461382199), - (2357,1017427547552923933,7826365750407107), (2371,18298921156206185323,7780153552808752), - (2377,18058718325419489529,7760514965801241), (2381,17276874961937127301,7747477561406783), - (2383,10241310285152218543,7740975272223899), (2389,13551291690816351229,7721533726960883), - (2393,2227793162265800425,7708626859051212), (2399,3252593890445660831,7689347258736786), - (2411,9357265865676806979,7651075932687495), (2417,5975920814941902737,7632082777703579), - (2423,2047946411815051335,7613183687044800), (2437,499583548980234061,7569447711821728), - (2441,15590181492856536249,7557043864690516), (2447,5435268687022716271,7538514129019023), - (2459,7749282890663670931,7501725934814783), (2467,14722999222186504715,7477399300247082), - (2473,12524093530027633305,7459257611690073), (2477,11342103845078581797,7447211979697033), - (2503,16596910768675153911,7369853804917919), (2521,18227227087509120617,7317232873347699), - (2531,6646950057377760203,7288322431335263), (2539,3465575786986788547,7265358043997460), - (2543,3358569605240866063,7253930032917637), (2549,10949362017858984541,7236855266265026), - (2551,16769109959597197255,7231181526346355), (2557,13101011825520745301,7214213560308780), - (2579,13311124746480603163,7152673157700485), (2591,17656474451099840991,7119546149637032), - (2593,8330558160552983009,7114054791249345), (2609,14154994877564784337,7070427011770621), - (2617,2283815468048106505,7048813172987983), (2621,15624483725156506901,7038055732052480), - (2633,11910165182417864697,7005979519069332), (2647,13603341304072929639,6968924848398017), - (2657,5963776123190253985,6942696301734870), (2659,7978095406079723339,6937474266156281), - (2663,4419460277516595543,6927053726515040), (2671,3549841427887199375,6906306279936185), - (2677,15855793094361478621,6890827072734236), (2683,3417082297664423091,6875417097916344), - (2687,14849388697965671807,6865182014778396), (2689,8472193726675826049,6860075892045203), - (2693,575390457553509965,6849886399446547), (2699,12705630690265304355,6834658789814580), - (2707,16695427772659180443,6814460315371094), (2711,10390327628386014503,6804405781523257), - (2713,8540033378761222569,6799389632771674), (2719,7639218031260373343,6784385462931059), - (2729,2142769465506019737,6759525127779242), (2731,13509149815971843,6754574907985921), - (2741,5155128041029374877,6729932168445659), (2749,7414933503619154069,6710347062098781), - (2753,8831387101034939713,6700597193501471), (2767,16100067559815167023,6666694641745410), - (2777,11511777990543267177,6642687819124793), (2789,14842055826964587245,6614106874761402), - (2791,10931893478292941015,6609367278290774), (2797,5111271597112943333,6595189157565088), - (2801,3839504389493990929,6585770822459675), (2803,14017682795933408827,6581071735180004), - (2819,9318255963448883115,6543719075455676), (2833,8647114765226362353,6511381600321055), - (2837,12601265426453687357,6502200942442563), (2843,10822781960938280723,6488478393847890), - (2851,1067594799074737291,6470271509543862), (2857,17813989114233340185,6456683259961341), - (2861,1972982763563482277,6447656090076739), (2879,12129102650757964991,6407344242344408), - (2887,9181839706934750839,6389589218465379), (2897,7144372402727689649,6367533335764429), - (2903,2923011461903683687,6354372743268877), (2909,16893133795930644725,6341266439913905), - (2917,9106380344923467373,6323875239530185), (2927,5123745449923425167,6302269926105074), - (2939,12345949504248617907,6276537622902195), (2953,12487315070553807545,6246780925739773), - (2957,386776507463642949,6238330765542628), (2963,273930725360519835,6225698303648178), - (2969,15172431467833858217,6213116899194864), (2971,13150523038746829459,6208934390343167), - (2999,8051613201895899655,6150965012907486), (3001,12760893267917703817,6146865735991186), - (3011,3394053874737659115,6126451037432597), (3019,6091886002480431587,6110216652437744), - (3023,14938018356745280303,6102131681676993), (3037,15847071217750484085,6074001999904363), - (3041,16426761904506894369,6066012520128099), (3049,3817610859465636953,6050096449232388), - (3061,17295705812331399261,6026378331822787), (3067,4559058365788014387,6014588873071259), - (3079,17218558774875365815,5991147799191150), (3083,1352242672934920099,5983374659004071), - (3089,13579765627586766065,5971752694629184), (3109,5684136642847780781,5933336787941316), - (3119,3761503440487103183,5914313585671545), (3121,4604297863960186065,5910523573761471), - (3137,12819222850075493313,5880377454163070), (3163,17274503934975558611,5832040491213895), - (3167,14584984894401236895,5824674478594743), (3169,10111074299789678497,5820998445474771), - (3181,3635997653007195493,5799039318990742), (3187,11414176125935122619,5788121767715579), - (3191,11781405334446902599,5780866209247744), (3203,8730959730172863019,5759208265285529), - (3209,1965966492118624697,5748440035434575), (3217,17322851677549442161,5734144878367905), - (3221,10663718554873388733,5727023928503431), (3229,5541449907555981749,5712834956243280), - (3251,15479150363912536699,5674175353340372), (3253,9611814080829292957,5670686773350615), - (3257,10279656276875295113,5663722466597958), (3259,3792365305119791219,5660246724059389), - (3271,2227595203031266551,5639481526661434), (3299,7162861218072729803,5591616875934995), - (3301,14054396045252808941,5588229043838095), (3307,9131333549640924099,5578090134172830), - (3313,11926630185899746321,5567987948599321), (3319,17407412605862704327,5557922287951055), - (3323,9281659973289909811,5551232041441333), (3329,4327698144057422593,5541226816974932), - (3331,1030049353860695467,5537899751939222), (3343,7432774234904805871,5518020961325022), - (3347,16142967849386099995,5511426373979549), (3359,15481206175584169695,5491736848380336), - (3361,18139389813629892321,5488468929993915), (3371,2670427501622741379,5472187503325289), - (3373,306260796954561189,5468942802760021), (3389,6221489665461793301,5443123066895707), - (3391,9770083266405884607,5439912731851828), (3407,3021216082515388847,5414365739274890), - (3413,12685176777320925181,5404847369970568), (3433,445988860506231513,5373359765135319), - (3449,8824913807370472649,5348432610527559), (3457,1371366279127380609,5336055560806928), - (3461,4130663581948830541,5329888492837200), (3463,3861937468506908727,5326810301388839), - (3467,10822231740964876835,5320664572745760), (3469,13655589155746938181,5317597023265941), - (3491,1976248147684724235,5284085956376268), (3499,13986628187353941251,5272004593800957), - (3511,2553437089097932807,5253985780036898), (3517,14135335592450168213,5245022483283921), - (3527,8849416210013201399,5230151424357684), (3529,17944934090406599801,5227187326072414), - (3533,13136713300156589829,5221269197200552), (3539,10956500718546899547,5212417087795860), - (3541,16279603284479624061,5209473051033479), (3547,10453328330464110163,5200660860927417), - (3557,9894964209344341997,5186039942004372), (3559,14139566685327242711,5183125617788578), - (3571,16742060359253054267,5165708225625749), (3581,13120317552565827413,5151282902460081), - (3583,10631461488197104127,5148407500337580), (3593,16916788678784573497,5134078506459658), - (3607,1493332206687881639,5114151392766717), (3613,8536660971835696181,5105658475978287), - (3617,17268641258938496481,5100012185156082), (3623,12876570732103631255,5091566125782376), - (3631,2667182770227902671,5080348133767433), (3637,15180397308939424797,5071967026040569), - (3643,4501552424245893875,5063613525585932), (3659,720930418841340771,5041471460428956), - (3671,13738326967453531495,5024991575513361), (3673,8708590858647525865,5022255397143901), - (3677,10826237071271474677,5016791970005317), (3691,11394900159322074691,4997763227772839), - (3697,419130782307709585,4989652170329876), (3701,3982423268007006685,4984259409270346), - (3709,10165851951108741845,4973508782342828), (3719,3625859079828363063,4960135540120879), - (3727,11992610917788635247,4949488616503770), (3733,1319389410040302781,4941533370937463), - (3739,17015999013165082515,4933603657049893), (3761,13002477675991497297,4904744502448697), - (3767,783509172230827783,4896932326442673), (3769,9925708936450774921,4894333795094070), - (3779,10304598237523382763,4881382395795065), (3793,9454381882228148785,4863365165755220), - (3797,10522951715474029181,4858241789230853), (3803,6330002896710745427,4850576932345398), - (3821,16868077412599103205,4827726792386692), (3823,14620359545733701647,4825201170209142), - (3833,3157073861819323209,4812612594236773), (3847,15996448721054084791,4795098537486236), - (3851,15850500166165906595,4790117910597131), (3853,15722581764355610565,4787631475138736), - (3863,16379066055610603687,4775237917087639), (3877,7550937024755496109,4757994344521421), - (3881,4515435936620477721,4753090459600502), (3889,6147333586918894033,4743312952869517), - (3907,8753586770580370795,4721459962556834), (3911,10055857418856753783,4716631059501291), - (3917,18117085639918469509,4709406197015458), (3919,5671938404904314799,4707002825646734), - (3923,15126988448922668251,4702203434542327), (3929,10653006440123943145,4695022670834703), - (3931,4368842211300837587,4692633954136238), (3943,9408166962269822039,4678352542153069), - (3947,15553778636256748867,4673611369067532), (3967,9128046033953075327,4650048922034169), - (3989,3838254595432170429,4624403127026711), (4001,9935699444849808481,4610533385081117), - (4003,16838471857440594955,4608229846042855), (4007,10680420826305505303,4603629666510993), - (4013,14433784298890603557,4596746592003376), (4019,8147044222651021179,4589884069099166), - (4021,13845380157785482909,4587601112586309), (4027,1575783452037766515,4580765848946995), - (4049,715272615355001137,4555876530923574), (4051,9325828650446102619,4553627270725636), - (4057,2259805719653351529,4546892796083202), (4073,17463944303516825689,4529031199044819), - (4079,10862730881355808527,4522369226209745), (4091,1848732600885093171,4509103904597788), - (4093,7918624318961075541,4506900579943696), (4099,5944900932268923563,4500303506638095), - (4111,12196120260847132399,4487167130554500), (4127,250307164557241311,4469770795665023), - (4129,15189859493972505569,4467605733521325), (4133,14023631715363031981,4463281895405166), - (4139,13931993712108252803,4456811808096050), (4153,1159306574341004809,4441787641153275), - (4157,4406451013998937877,4437513609263784), (4159,7069995204013711295,4435379676294674), - (4177,13182554718703138993,4416266237421487), (4201,10204768680623898585,4391036437445739), - (4211,6965168149417759931,4380608899004880), (4217,12773178253552736713,4374376114230389), - (4219,7913867450441879219,4372302458807668), (4229,14778332684258207821,4361963602201360), - (4231,248514396644160823,4359901695511593), (4241,13549070452630335601,4349621333107651), - (4243,12334059141436247451,4347571075585564), (4253,17570599633810814389,4337348712369986), - (4259,15835007357004489483,4331238336160965), (4261,15078622297284761389,4329205368155257), - (4271,15401800366857471567,4319069087733446), (4273,14306695497372678225,4317047524855968), - (4283,11396237408133428339,4306968030284742), (4289,6829897316169449281,4300942894313255), - (4297,10826783466114845049,4292935553574482), (4327,3465958616114135767,4263171729537682), - (4337,4249088616471257105,4253341958429686), (4339,3804986389944698939,4251381441278993), - (4349,8788607431760448597,4241605903359289), (4357,1752800561513829325,4233817781434370), - (4363,4879106729557832355,4227995432892402), (4373,14042810661188908605,4218327023487205), - (4391,17963625064719208087,4201034860785595), (4397,15606524438071305893,4195302268298738), - (4409,3782231037113502985,4183883890612282), (4421,1969432979595319693,4172527499142626), - (4423,1259533508989438071,4170640758243172), (4441,1013511721230608105,4153736562420525), - (4447,10581885345633700511,4148132240546334), (4451,14928144721074321483,4144404420065053), - (4457,15160516836885368537,4138825235294940), (4463,8303721452852899215,4133261051693827), - (4481,14552385695283031681,4116657905313446), (4483,8295479824358343979,4114821341447591), - (4493,15778063092647631173,4105663047787569), (4507,8402743639522012307,4092909712382860), - (4513,662169851526910561,4087468219301917), (4517,3695882972483317293,4083848588379356), - (4519,2249204687898641943,4082041175859604), (4523,3597176270840553731,4078431146077725), - (4547,4819602366300186347,4056904348737530), (4549,1184095245003998477,4055120702068487), - (4561,12804733991967647537,4044451671499572), (4567,8667990536934683111,4039138181237037), - (4583,4512066355362951639,4025036891492374), (4591,9422264180537769231,4018023104706937), - (4597,13996572401370223197,4012778784796508), (4603,5570491910157783347,4007548136804160), - (4621,14482749945773264069,3991937691778738), (4637,16867413170698403893,3978163483655283), - (4639,13106373888110946783,3976448388383175), (4643,1326989558608440715,3973022630564193), - (4649,5773287293449644569,3967895047044429), (4651,16011504155142003843,3966188792455289), - (4657,2150865800305837777,3961078821926036), (4663,636913102266188679,3955982001653345), - (4673,5542313006524333505,3947516386413342), (4679,13912921529412482935,3942454386345277), - (4691,2355489170784911835,3932369233363792), (4703,18325151671777806751,3922335546185318), - (4721,2961794536723541649,3907380655308102), (4723,13908290418479719099,3905726037202953), - (4729,3237639581556127689,3900770580188105), (4733,18244075429755844309,3897473922186678), - (4751,1615206384900689007,3882707656011271), (4759,17136594988415618343,3876180725721696), - (4783,3089241480878392399,3856730937426207), (4787,11117371350042209403,3853508266912377), - (4789,7965727029532543901,3851898950450939), (4793,16872632175911261065,3848684346695086), - (4799,7976035414241991999,3843872488791321), (4801,15891633719821434177,3842271208854311), - (4813,13560062441883314693,3832691475942146), (4817,4702636853335131697,3829508838220791), - (4831,8923626764698659103,3818411110269002), (4861,4770120818895886933,3794845520203569), - (4871,11845907506171931319,3787054829338852), (4877,9005884281218462661,3782395750196750), - (4889,14832102874565810473,3773111898897433), (4903,17190123123144797335,3762338175343575), - (4909,5264593287281947813,3757739676860776), (4919,7211443149775049351,3750100441900701), - (4931,13205639136117363051,3740974259523332), (4933,8869993298771347341,3739457545856385), - (4937,15565958235988250361,3736427805085993), (4943,8564693030379004847,3731892387964707), - (4951,3968043312159295591,3725862264938305), (4957,9638302834558753013,3721352445775580), - (4967,16541533743568017495,3713860292673555), (4969,10357499691215465689,3712365480722389), - (4973,5515847262740016741,3709379463846682), (4987,7294361201795716019,3698966126671255), - (4993,964270018673781889,3694521144343991), (4999,13125638861809336887,3690086832108331), - (5003,9487002298951564323,3687136532822216), (5009,2938810495272553841,3682719918887912), - (5011,17154625301035025051,3681250064599790), (5021,14901412858587122357,3673918357639823), - (5023,8751461502617929823,3672455519352887), (5039,7526593731999769423,3660794616731405), - (5051,3031240859469199731,3652097421047228), (5059,14629044717082965227,3646322212632842), - (5077,14050336681708653949,3633394538843717), (5081,10953321564727753833,3630534161328390), - (5087,4587208817228736543,3626252029429831), (5099,15849222550876945603,3617717998374103), - (5101,7395332607476187621,3616299563558037), (5107,10818092520219327803,3612050924948022), - (5113,14341053724427042377,3607812257717494), (5119,4551325994353421311,3603583526803975), - (5147,12293050742728533523,3583979808375665), (5153,2233799398795800545,3579806728839423), - (5167,11445763789493482191,3570107233154548), (5171,5586463202364950267,3567345595379917), - (5179,3344563175364601075,3561835117534186), (5189,16850562133240176269,3554970914185691), - (5197,4678239116634440837,3549498571042823), (5209,4228337958151123945,3541321572990891), - (5227,12210777596142155843,3529126472873455), (5231,818131260772436623,3526427848157054), - (5233,5062014999015271569,3525080082879715), (5237,16544654747797167069,3522387640578489), - (5261,7296649765707959877,3506318964780374), (5273,10047230984201371561,3498339479178750), - (5279,6384201822820108127,3494363340350360), (5281,2997028292982919009,3493039968511560), - (5297,8566922866023314513,3482488969928176), (5303,12933244289280051463,3478548759892429), - (5309,6038885138464343701,3474617455963373), (5323,4168971091616116963,3465478879148891), - (5333,15983949815228171389,3458980700114298), (5347,6623854240045322443,3449924083356938), - (5351,13155069217954709207,3447345182902177), (5381,15004905930240978893,3428125640904952), - (5387,14803280978401037987,3424307420402738), (5393,17827633990761020401,3420497695848238), - (5399,7250229843380564647,3416696438916382), (5407,17075264303479989983,3411641219476521), - (5413,8267467416002100909,3407859610882976), (5417,6194319267136362265,3405343192488379), - (5419,9225074080042975619,3404086376399621), (5431,9948538647007047815,3396564918746004), - (5437,11023261264572803605,3392816640373285), (5441,6736570570568071873,3390322380758969), - (5443,1633534933589565291,3389076625704492), (5449,8693565568230157561,3385344847441650), - (5471,7279568717810075295,3371731689583175), (5477,14122183293968258157,3368037990452720), - (5479,17918155130549778007,3366808555157793), (5483,9891195983349641027,3364352375288993), - (5501,10026497869549456341,3353343769080085), (5503,305043378285947519,3352125036109313), - (5507,2599359615253061931,3349690225841574), (5519,8001722288903907695,3342406971137806), - (5521,12486050100244990833,3341196173466682), (5527,15569759562846943783,3337569038123674), - (5531,2498031334516082835,3335155319781151), (5557,15827618453022699677,3319550850046707), - (5563,1369495830027331443,3315970532753829), (5569,14359245027748411969,3312397930276450), - (5573,15080453256741560589,3310020468995074), (5581,13835884374224723717,3305275770240019), - (5591,16546310414890610151,3299363991005106), (5623,13912972010777557959,3280587599806073), - (5639,843990064021469111,3271279317912670), (5641,4133431042221037625,3270119495428036), - (5647,7993480210442229999,3266644957271038), (5651,5957407172981761051,3264332697524252), - (5653,3899497464723671357,3263177794747842), (5657,3759783616225404457,3260870439050654), - (5659,6816070305376687123,3259717984398224), (5669,14714442882574456237,3253967908574625), - (5683,2054687488766170363,3245951798998689), (5689,17999275154361350153,3242528401073923), - (5693,14694534406160691477,3240250144688134), (5701,11150233306087197837,3235703222892396), - (5711,16615312820024852655,3230037484452731), (5717,10486604554758797053,3226647555310399), - (5737,2205763715280591321,3215399001866751), (5741,2609084861148259173,3213158695995393), - (5743,346900289040681103,3212039713339639), (5749,2717758258902763997,3208687436721090), - (5779,4197520065223751579,3192030467850761), (5783,10344594679412082983,3189822596180105), - (5791,8043175407721743711,3185416003058116), (5801,10566890287353359769,3179924853251086), - (5807,10819633255563067471,3176639241210530), (5813,13007604327909074845,3173360411785575), - (5821,1191543681792611477,3168999153703753), (5827,819925641855289835,3165736068939342), - (5839,14295515830370906159,3159230017761526), (5843,14490938781161533787,3157067272584212), - (5849,649688712460962153,3153828701266806), (5851,1588986329370981715,3152750653513852), - (5857,16739703730880359713,3149520927729136), (5861,13656444725443737325,3147371450897381), - (5867,5499123126797001155,3144152731158948), (5869,2618186712114509541,3143081287052232), - (5879,15525512787330304711,3137735001481468), (5881,9798950601303968585,3136667926153639), - (5897,6043600059421206329,3128157380652798), (5903,9878054890224613359,3124977820381086), - (5923,2229928880090501259,3114425810182264), (5927,13031300394233489559,3112323953721874), - (5939,8684474899830258683,3106035371899234), (5953,167331459764877505,3098730736386620), - (5981,1761091935477036277,3084224055126158), (5987,4159529731001819723,3081133134075422), - (6007,5008596568040665671,3070874658516655), (6011,1224463630911680435,3068831155167118), - (6029,6296798690279359301,3059668945713974), (6037,9414347936243022781,3055614390211951), - (6043,12027167243159959187,3052580518568517), (6047,9465891658792911967,3050561282240706), - (6053,5250906994713622573,3047537431638782), (6067,12578569347772608379,3040505039345566), - (6073,2019938219828231817,3037501082448468), (6079,12930017519012403263,3034503055388970), - (6089,13023904216271532665,3029519473429060), (6091,3534288349042693603,3028524720687826), - (6101,4934451127404358013,3023560739831101), (6113,14047046239672495137,3017625400574112), - (6121,12365134934558126169,3013681436645899), (6131,13226535140764506427,3008765955587922), - (6133,12392073305671507037,3007784782929977), (6143,9690321199065720831,3002888502964276), - (6151,17867940365983012279,2998982941588286), (6163,5827650610337903131,2993143610856652), - (6173,16486422655865154101,2988294844274996), (6197,10207178542641609245,2976721651397378), - (6199,14244969169357577607,2975761263705364), (6203,16347211377266065651,2973842346237232), - (6211,13388813763368645739,2970011926213097), (6217,2222392039763302905,2967145580458348), - (6221,5610229832415764613,2965237754976619), (6229,9361078506501186813,2961429454761526), - (6247,17153375432076002135,2952896442085729), (6257,17739181571281823889,2948177093448865), - (6263,3572712847103574343,2945352718139797), (6269,15030462390893027541,2942533749195972), - (6271,15458083257430026111,2941595291613706), (6277,13198076730130571341,2938783507043102), - (6287,11343265880222860911,2934109125768975), (6299,12282210612023790995,2928519459233140), - (6301,3940536029711642037,2927589918062141), (6311,14059394548335120151,2922951049549921), - (6317,17115144374863334181,2920174778171529), (6323,9411544580387001979,2917403775693429), - (6329,17248827844558876041,2914638027130597), (6337,14927395235913299777,2910958509343467), - (6343,6293355537680509175,2908204961959569), (6353,3205604510841389105,2903627274312852), - (6359,12865436384164469479,2900887572528628), (6361,17086655570240005993,2899975487141888), - (6367,14680328603971461919,2897242669029299), (6373,10177114728254006509,2894514996659273), - (6379,9323138876569931715,2891792455511765), (6389,11153509525237125981,2887266250384966), - (6397,15969684020666483797,2883655475021033), (6421,14505156646653095485,2872877133423072), - (6427,10054293525782567187,2870195125830022), (6449,12242528242437103569,2860403794961940), - (6451,8564253371688126971,2859516985538606), (6469,15991550589791801741,2851560376211091), - (6473,5639750737196230905,2849798250225483), (6481,5610018912094048177,2846280523639801), - (6491,9128168535627034323,2841895559037059), (6521,8557184607111086281,2828821357722673), - (6529,14697497728815605377,2825355195850750), (6547,518436063779220635,2817587303147938), - (6551,13597821268805285415,2815866901802709), (6553,17436156385252092585,2815007488739440), - (6563,17465803393879499275,2810718280315336), (6569,10626043473118730905,2808151023551461), - (6571,18101446627192084739,2807296313150137), (6577,7505471665082371921,2804735300852904), - (6581,1345454665762131101,2803030553671106), (6599,7161775771608406007,2795384766435755), - (6607,3696608014770916655,2792000011156281), (6619,15353242650259241555,2786938219324603), - (6637,8357595213145189349,2779379851395141), (6653,1186713732684155733,2772695637112513), - (6659,12391092692852203691,2770197337995127), (6661,4536220806596043469,2769365571792456), - (6673,10526779774117484273,2764385444883793), (6679,13467034601498394023,2761902092185888), - (6689,17961376013166438881,2757773071267685), (6691,8973868175149393291,2756948748125773), - (6701,16605097784303240613,2752834513312871), (6703,14324228390818770127,2752013139446449), - (6709,9246743228481923101,2749551956134975), (6719,4530008590805292479,2745459752003207), - (6733,3843870776090078853,2739751087733484), (6737,5292794462591741617,2738124398650668), - (6761,3486901187132200409,2728404684766979), (6763,8150062293692760643,2727597822521004), - (6779,5891311538513228979,2721160063978396), (6781,6999479796734209749,2720357480269805), - (6791,11036536765054028599,2716351652732962), (6793,12073343758532705209,2715551902503982), - (6803,4238168600206971803,2711560204866904), (6823,627237963520535831,2703611911726447), - (6827,1680661317393780739,2702027841469100), (6829,6950281520230586661,2701236502227200), - (6833,3018214528670756433,2699655213480104), (6841,9284043245984795529,2696498183556432), - (6857,14225810509227958137,2690206223378963), (6863,14941782064075680815,2687854301866465), - (6869,9963229074605100669,2685506489111886), (6871,15958004187764455655,2684724796057277), - (6883,2355758832019569355,2680044177496665), (6899,17246194995713379899,2673828681505950), - (6907,17672231871396569139,2670731732113732), (6911,16193951135175206143,2669185946130741), - (6917,370695016082930125,2666870619301655), (6947,6718045560167722123,2655353976350878), - (6949,5802933162344089773,2654589735747525), (6959,7962928466363485135,2650775121958550), - (6961,12534563923092397521,2650013514395855), (6967,977012855346465415,2647731315302074), - (6971,3191331710356293107,2646212031804554), (6977,14766384642635494593,2643936372898029), - (6983,2826581148341575287,2641664624618294), (6991,16045580133346843567,2638641692706272), - (6997,9506782782592059901,2636379030114270), (7001,5401489123140205801,2634872742995222), - (7013,5523764801766727277,2630364191317489), (7019,1952689962496964931,2628115696496588), - (7027,4502087104939786683,2625123676349729), (7039,9670192588718318719,2620648398026644), - (7043,12207904888195402539,2619160027503840), (7057,13242341714242962801,2613964017813454), - (7069,10281535104033899189,2609526676150735), (7079,16080641005630970903,2605840383346454), - (7103,17083300368416363583,2597035629129881), (7109,12639483806870055693,2594843729597629), - (7121,11885081001289063729,2590471011614878), (7127,16831651004817344487,2588290174506742), - (7129,16953719619995087977,2587564044565794), (7151,7261583634106053391,2579603422417780), - (7159,5158595004269663687,2576720781353478), (7177,17238722656035942969,2570258335475763), - (7187,10628630472969424411,2566682075095248), (7193,9324671409983029289,2564541091854518), - (7207,6974799167595189143,2559559327557867), (7211,12552790621230449283,2558139519305165), - (7213,5431981756905460645,2557430205699369), (7219,9740821223019921147,2555304623037754), - (7229,13549897777202617109,2551769826215182), (7237,779978400795235981,2548949022206653), - (7243,1319261829377543523,2546837508450856), (7247,6600304592676813487,2545431775039264), - (7253,4702609925863637245,2543326082132848), (7283,11559925848195852475,2532849659990327), - (7297,1266523061659378561,2527990143032691), (7307,7389300657417251619,2524530460340707), - (7309,9509827838245668421,2523839659831652), (7321,7339894206626953129,2519702782913475), - (7331,7936302115465819915,2516265730965700), (7333,4512949525192272685,2515579445480642), - (7349,8313459841083961757,2510102609022935), (7351,7613579311608594695,2509419680820235), - (7369,10356110765766917497,2503290008645616), (7393,13329163646930396961,2495163543042006), - (7411,12017390418009676859,2489103234881871), (7417,16529197939041887561,2487089668829655), - (7433,16411720511158518073,2481736051891504), (7451,4867306247337669907,2475740715838082), - (7457,13959363927577175777,2473748702388299), (7459,7204097799532903051,2473085410069654), - (7477,16714817587184995613,2467131747185977), (7481,8879391178910318857,2465812601752379), - (7487,8327767459481539263,2463836526473828), (7489,2943498353329271489,2463178538350854), - (7499,7741285984793166947,2459893862342919), (7507,6275873766385266395,2457272422233855), - (7517,15651634122937278197,2454003468632373), (7523,10828236319221238859,2452046267939592), - (7529,4687026353168597721,2450092186706010), (7537,14956621073960338321,2447491584676867), - (7541,1223096676416228061,2446193352832456), (7547,11989039311189260723,2444248585359686), - (7549,8528167547654833109,2443601016520009), (7559,8011729169729919031,2440368312436770), - (7561,7380161463162464441,2439722797739657), (7573,10532645104281011645,2435856869630206), - (7577,8104686686205503145,2434570948094173), (7583,11637771811766648415,2432644609482995), - (7589,3417594171516092973,2430721316867775), (7591,14242704125413210647,2430080894968983), - (7603,2938183226787092859,2426245439130547), (7607,6697766153751252999,2424969642922249), - (7621,10459044894698723597,2420514902730553), (7639,12602900552518673895,2414811372392924), - (7643,8312257829367486035,2413547569502754), (7649,8303325904795657761,2411654343536351), - (7669,1820861294014621277,2405364985488271), (7673,17468270877045953609,2404111048313508), - (7681,13079152223072805377,2401607092007492), (7687,12399418060212989879,2399732545038318), - (7691,16966879154521046435,2398484471942471), (7699,12504683377151597595,2395992216354013), - (7703,16902131594475141543,2394748029820790), (7717,12155201971596873133,2390403534237339), - (7723,5099546626617880707,2388546429329218), (7727,11158286760776296655,2387309961655176), - (7741,15213023403508820245,2382992387767672), (7753,6999912429363278841,2379304020857674), - (7757,9407673012194790021,2378077101161473), (7759,4426838183431780527,2377464115699130), - (7789,8521168978971237221,2368307109219354), (7793,10912291823405752977,2367091501823373), - (7817,15223224513176451001,2359823982820717), (7823,5647443698905071727,2358014070524038), - (7829,13225389511525317821,2356206932393607), (7841,3761808924099167585,2352600953157703), - (7853,14765851680547337509,2349005994360060), (7867,16228538926419703411,2344825737092862), - (7873,17809437533883691329,2343038749359780), (7877,3187256402731839501,2341848936614136), - (7879,15749618908978823927,2341254483273201), (7883,13069271299209418467,2340066481505715), - (7901,7641588830939294069,2334735359284843), (7907,12420698804657854155,2332963712369995), - (7919,12818844884155027471,2329428472497733), (7927,7937661667140567751,2327077592242910), +pub const P_INVS_U64: &'static [(u64, u64, u64)] = &[ + (3, 12297829382473034411, 6148914691236517205), (5, 14757395258967641293, 3689348814741910323), + (7, 7905747460161236407, 2635249153387078802), (11, 3353953467947191203, 1676976733973595601), + (13, 5675921253449092805, 1418980313362273201), (17, 17361641481138401521, 1085102592571150095), + (19, 9708812670373448219, 970881267037344821), (23, 15238614669586151335, 802032351030850070), + (29, 3816567739388183093, 636094623231363848), (31, 17256631552825064415, 595056260442243600), + (37, 1495681951922396077, 498560650640798692), (41, 10348173504763894809, 449920587163647600), + (43, 9437869060967677571, 428994048225803525), (47, 5887258746928580303, 392483916461905353), + (53, 2436362424829563421, 348051774975651917), (59, 14694863923124558067, 312656679215416129), + (61, 5745707170499696405, 302405640552615600), (67, 17345445920055250027, 275324538413575397), + (71, 1818693077689674103, 259813296812810586), (73, 9097024474706080249, 252695124297391118), + (79, 11208148297950107311, 233503089540627235), (83, 11779246215742243803, 222249928598910260), + (89, 17617676924329347049, 207266787345051141), (97, 11790702397628785569, 190172619316593315), + (101, 4200743699953660269, 182641030432767837), (103, 15760325033848937303, 179094602657374287), + (107, 8619973866219416643, 172399477324388332), (109, 12015769075535579493, 169236184162472950), + (113, 10447713457676206225, 163245522776190722), (127, 9150747060186627967, 145249953336295682), + (131, 281629680514649643, 140814840257324821), (137, 16292379802327414201, 134647766961383588), + (139, 4246732448623781667, 132710389019493177), (149, 16094474695182830269, 123803651501406386), + (151, 8062815290495565607, 122163868037811600), (157, 6579730370240349621, 117495185182863386), + (163, 2263404180823257867, 113170209041162893), (167, 10162278172342986519, 110459545351554201), + (173, 9809829218388894501, 106628578460748853), (179, 17107036403551874683, 103054436165975148), + (181, 3770881385233444253, 101915713114417412), (191, 2124755861893246783, 96579811904238490), + (193, 8124213711219232577, 95578984837873324), (197, 14513935692512591373, 93638294790403815), + (199, 2780916192016515319, 92697206400550510), (211, 13900627050804827995, 87425327363552377), + (223, 7527595115280579359, 82720825442643729), (227, 1950316554048586955, 81263189752024456), + (229, 2094390156840385773, 80553467570784068), (233, 7204522363551799129, 79170575423646144), + (239, 7255204782128442895, 77183029597111094), (241, 17298606475760824337, 76542506529915151), + (251, 2939720171109091891, 73493004277727297), (257, 18374966859414961921, 71777214294589695), + (263, 15430736487513693367, 70139711306880424), (269, 10354863773718001093, 68575256779589411), + (271, 15383631589145234927, 68069166323651481), (277, 17181443938689762877, 66594743948409933), + (281, 14245350405676059433, 65646776063023315), (283, 5149444458738708755, 65182841249857072), + (293, 2707201348701401773, 62958170900032599), (307, 17305088903023944187, 60087114246610917), + (311, 9134400602415662215, 59314289626075728), (313, 6365010734698503433, 58935284580541698), + (317, 17050145153302519317, 58191621683626345), (331, 3455281367280943203, 55730344633563600), + (337, 9196002980365592497, 54738112978366622), (347, 9941040754419844819, 53160645745560667), + (349, 15751088062938241781, 52856000211202153), (353, 8779186981255537313, 52257065364616293), + (359, 5600822016808749655, 51383688227603207), (367, 9751139919072624015, 50263607830271257), + (373, 3511310534137743069, 49455077945602015), (379, 17181268226964305331, 48672147951740241), + (383, 14834457375202459263, 48163822646761231), (389, 12661389891209383757, 47420935922132523), + (397, 185861401246443845, 46465350311610961), (401, 3220129888178724721, 46001855545410353), + (409, 2074694932495450793, 45102063749901104), (419, 1849076971589024267, 44025642180691053), + (421, 14897608040525528621, 43816494236839790), (431, 8046375605237577039, 42799870240625409), + (433, 7540585914657253201, 42602180308798040), (439, 15379290047785184263, 42019918163347497), + (443, 15615189678648040307, 41640505809728107), (449, 205420312624827969, 41084062524965593), + (457, 686202733595322489, 40364866682077793), (461, 3041111821262312197, 40014629227135686), + (463, 8127723090792113455, 39841779856824085), (467, 15247201739725667931, 39500522641776341), + (479, 8010277176057592351, 38510947961815347), (487, 2386334448960373207, 37878324586672590), + (491, 1051952818867347139, 37569743530976683), (499, 12494988971771199291, 36967422993405915), + (503, 17969989256695189447, 36673447462643243), (509, 5436172123882971989, 36241147492553146), + (521, 1805727346946616377, 35406418567580713), (523, 7195288319381928355, 35271021173440825), + (541, 13911777416032342069, 34097493666745936), (547, 13219604528142859659, 33723480939139948), + (557, 5133295029488295333, 33118032448311582), (563, 18151858289227516155, 32765087164670606), + (569, 6386658317259721737, 32419585366800617), (571, 1873749835858413299, 32306031652731263), + (577, 8184343991108570561, 31970093715267853), (587, 8107768264083584867, 31425458387920871), + (593, 13407330009728190129, 31107494222107169), (599, 16999336775772408167, 30795899956109435), + (601, 10926856722530117097, 30693417759916059), (607, 7810235958720518559, 30390023185682951), + (613, 10111102787547160429, 30092567820080834), (617, 5112468778937331161, 29897478239399597), + (619, 10400506755613301315, 29800878955912038), (631, 14909412801254946631, 29234142747558718), + (641, 18417966001831689601, 28778071877862015), (643, 12450835035754191915, 28688559990217032), + (647, 16650538700226241335, 28511196404496988), (653, 18023005695293558853, 28249225227732850), + (659, 13744083976011213723, 27992024391061535), (661, 3544230707051608253, 27907328401981167), + (673, 7016889276180750689, 27409723735081057), (677, 7711120491668837677, 27247775588935822), + (683, 18338710433453565955, 27008410063996415), (691, 16604739238563445883, 26695722248494285), + (701, 4578792394900801685, 26314898821268975), (709, 17796294705807240205, 26017974716092456), + (719, 7799457855921701935, 25656111368163493), (727, 3501582781529460967, 25373788271952615), + (733, 8027982755134170485, 25166090141486427), (739, 12755461734324196043, 24961764646426998), + (743, 8416482154761154775, 24827380987496031), (751, 73688724661955599, 24562908220651866), + (757, 11233750354002778461, 24368222026036395), (761, 8193166224591101769, 24240136759145271), + (769, 8635666926574042369, 23987963684927895), (773, 11955781087876436429, 23863834506739394), + (787, 1757948926973591323, 23439319026314550), (797, 3332912354597459765, 23145224684704581), + (809, 12062209660064712985, 22801908620160137), (811, 2229076349227541379, 22745677032934095), + (821, 4044353146489304861, 22468628591607249), (823, 5536264624794968711, 22414026821032261), + (827, 9502192231439261171, 22305615566758829), (829, 9813044796750195733, 22251802260204525), + (839, 17941052639030982263, 21986584116459537), (853, 13018686907823153661, 21625725760503577), + (857, 12247604875076703465, 21524788884141833), (859, 858986918449804499, 21474672961245112), + (863, 13637338028999645343, 21375137976488472), (877, 4964004106494246501, 21033915705484095), + (881, 14447506709261737361, 20938415520669184), (883, 17047047751015848379, 20890989890950794), + (887, 15763959422628906567, 20796780240935232), (907, 11979197639928253475, 20338196332645591), + (911, 16462352285319281519, 20248895799900715), (919, 16098246732442938407, 20072626848432591), + (929, 13264181960428396641, 19856559821000593), (937, 11792529028977610905, 19687026759561954), + (941, 1725094026021722149, 19603341204792297), (947, 18271431828024877947, 19479138409408185), + (953, 18137040080866579081, 19356499552685783), (967, 9614435380713147895, 19076260676018150), + (971, 10828675717831559651, 18997676697950104), (977, 12064963626510136625, 18881007240234955), + (983, 9326583728009813991, 18765762028188760), (991, 13160290676198438943, 18614272526447579), + (997, 11785933776281829869, 18502250826188115), (1009, 6965519813759503633, 18282204235589248), + (1013, 7775675932353384541, 18210013893099261), (1019, 10372899268140896051, 18102791043875909), + (1021, 7497942008412795221, 18067330140753723), (1031, 13544311604071901623, 17892089305246897), + (1033, 15464550210873641529, 17857448280454551), (1039, 1881958490676816623, 17754325383743553), + (1049, 8370495880920635433, 17585075380085368), (1051, 15691141010367591955, 17551611868420125), + (1061, 10466484384894580653, 17386186685871396), (1063, 5917535022704569239, 17353475139896097), + (1069, 13511506650808773541, 17256074905247475), (1087, 4836542834413267903, 16970325734783396), + (1091, 12613447368457676907, 16908106392034419), (1093, 12235946434985750157, 16877167496532069), + (1097, 14007418243755748857, 16815628143764404), (1103, 13546566364192871087, 16724156005176384), + (1109, 14687533829653321981, 16633673646266502), (1117, 17043007953507839989, 16514542590608372), + (1123, 10923494932339137867, 16426308168931034), (1129, 8610659102608444377, 16339011579902171), + (1151, 2852754513571068799, 16026710750399262), (1153, 16894849732729650049, 15998910731751562), + (1163, 14877941479913636643, 15861344861315177), (1171, 10554499171123313051, 15752983837497482), + (1181, 9918444103984390581, 15619597014148646), (1187, 6884505159775342347, 15540643701524474), + (1193, 17503532515875282841, 15462484554660143), (1201, 10275496907003905105, 15359487155461741), + (1213, 12439766407497455253, 15207538395473661), (1217, 6745111842892974913, 15157554703130280), + (1223, 5399782811437464823, 15083192210719175), (1229, 11572367518982965253, 15009555796346258), + (1231, 1168843247562424879, 14985169840543908), (1237, 12988774525627339901, 14912485104049758), + (1249, 2171073962238033697, 14769210627469616), (1259, 2754557494723904451, 14651901567680342), + (1277, 8710561218830743637, 14445375155606540), (1279, 10802667170608642815, 14422786609624356), + (1283, 17756608675784330667, 14377820790108769), (1289, 715544766241642809, 14310895324832856), + (1291, 10173572254439349923, 14288725076459761), (1297, 9401154844041645041, 14222624574949538), + (1301, 4069343235322552893, 14178896290322483), (1303, 17455744775812645543, 14157132827098658), + (1307, 11545093077501463827, 14113805718216948), (1319, 7286393982109686423, 13985401117293064), + (1321, 10375420777264342809, 13964227156479600), (1327, 17848997280062595535, 13901088224347815), + (1361, 8864195903163884465, 13553816365694012), (1367, 11915490136858474087, 13494326315808011), + (1373, 7241656996161287925, 13435356208091443), (1381, 10365440551193781357, 13357526483497140), + (1399, 11511084757933122631, 13185664098434275), (1409, 11062809611273648769, 13092082380205501), + (1423, 11991031811792927087, 12963277634370731), (1427, 10910337770294927515, 12926940486131430), + (1429, 4001742941112638909, 12908848197137544), (1433, 6539390083352723113, 12872815124710084), + (1439, 3589359513994909279, 12819141121410390), (1447, 15973580044476895767, 12748268191920906), + (1451, 6496406768894266627, 12713124792356686), (1453, 16301183338364118565, 12695625652931556), + (1459, 12921571242858918267, 12643416088903051), (1471, 15612641993044453951, 12540274693208396), + (1481, 7535638193514030201, 12455600319857901), (1483, 10846635760131307491, 12438802477214802), + (1487, 7517637463798243631, 12405342349502052), (1489, 9155234298503263025, 12388679700275051), + (1493, 17211195240909179773, 12355488328003718), (1499, 11419998999601376851, 12306033404742862), + (1511, 5310611298519956951, 12208301835678061), (1523, 3355054568888736571, 12112110356999048), + (1531, 13325995392242171187, 12048820426982071), (1543, 7651274275550300087, 11955116055547343), + (1549, 15826806245293734085, 11908808310980988), (1553, 14028077753413380849, 11878135269613362), + (1559, 9773579605442007463, 11832420829832938), (1567, 5579934072072959455, 11772012810280505), + (1571, 4004035473669609867, 11742039512227594), (1579, 17874299197451307139, 11682548495066213), + (1583, 11163601277709254863, 11653028473600474), (1597, 8663154699613126933, 11550872932817502), + (1601, 13918592655241185729, 11522013787451312), (1607, 1503748272343466871, 11478994445369976), + (1609, 4574425659049167865, 11464725962529242), (1613, 2904818967589724805, 11436295147991042), + (1619, 3999263230310100443, 11393912337065813), (1621, 9707015851248764669, 11379854456329149), + (1627, 10045368930120874451, 11337888182980670), (1637, 13127951646836669293, 11268628023035767), + (1657, 2237655738573095881, 11132615614791521), (1663, 5291098570751326591, 11092449833860223), + (1667, 12747839935760889899, 11065833277570216), (1669, 12312566146262696525, 11052572842246585), + (1693, 14633182097455361973, 10895891360726256), (1697, 3782832609104846177, 10870208646853006), + (1699, 15080946155610692875, 10857412639028576), (1709, 5137887758388383013, 10793881845353745), + (1721, 4062356771607158665, 10718619450150814), (1723, 2141235527998787187, 10706177639993935), + (1733, 18372233278258907149, 10644399350092066), (1741, 3401151549489239557, 10595487693112895), + (1747, 8806287668845887835, 10559097924275644), (1753, 5387754116223211881, 10522957258248460), + (1759, 4184338195230307615, 10487063145940620), (1777, 7816768873102584337, 10380835156842741), + (1783, 6114428349726497479, 10345902453005917), (1787, 17001559870956704819, 10322744305377477), + (1789, 18085851931406681685, 10311204065796283), (1801, 15916846357881534265, 10242500873797641), + (1811, 13751024019606788891, 10185943718227251), (1823, 16463440816196072671, 10118894170987137), + (1831, 11374316799136037015, 10074682727312698), (1847, 10307005892836089479, 9987408810887683), + (1861, 10526836220461872013, 9912275160510237), (1867, 12903828473628641891, 9880419964493600), + (1871, 5176130752911552431, 9859296672212480), (1873, 10567728986166763953, 9848768859428484), + (1877, 8451891264459357693, 9827780540069020), (1879, 13538084128603231335, 9817319890212640), + (1889, 13896091485912489121, 9765348900852065), (1901, 9383483176894863973, 9703705456975040), + (1907, 2843913349591299515, 9673174658473807), (1913, 12053544219622027977, 9642835375697622), + (1931, 10661090826649331747, 9552948769399042), (1933, 6680145293117788997, 9543064704453984), + (1949, 13790100623599187637, 9464722459573910), (1951, 7043989920509285471, 9455020027529242), + (1973, 17128451669050125981, 9349591522407274), (1979, 736378363730699635, 9321245110515185), + (1987, 11864589293508206827, 9283716192103448), (1993, 11727057070441546361, 9255767222132238), + (1997, 13994400236189269253, 9237227878672784), (1999, 2768395808960913199, 9227986029869710), + (2003, 16319336244939253851, 9209557700304319), (2011, 15043590393278798931, 9172920971511462), + (2017, 493864243916864545, 9145634146608602), (2027, 11384744369122175171, 9100515083231155), + (2029, 5309462069515218405, 9091544639580853), (2039, 9698337247188150727, 9046956387302379), + (2053, 11797649765601871053, 8985262578523892), (2063, 3818109413220542191, 8941708227682768), + (2069, 3798121302755084093, 8915777705997849), (2081, 15698790847928695777, 8864365244454373), + (2083, 13345772116697212811, 8855854092035310), (2087, 12993154666196952983, 8838880725304049), + (2089, 7205621428505023513, 8830418417285568), (2099, 9913257415504704251, 8788348772610553), + (2111, 6859637185154901951, 8738391318668664), (2113, 34920480972474305, 8730120243118576), + (2129, 5588609641870672049, 8664511072667708), (2131, 16317274790681607131, 8656379199300587), + (2137, 13327923654566002665, 8632074905806996), (2141, 15749952436590873589, 8615947722423891), + (2143, 11310789413371138975, 8607906707283971), (2153, 15473673849103321049, 8567925719326312), + (2161, 6700922766248032401, 8536207345538894), (2179, 4893170295825663531, 8465692553331597), + (2203, 10433337773872946579, 8373465308084226), (2207, 10364278500860826463, 8358289113597440), + (2213, 8552354007964753709, 8335627688074808), (2221, 17059708386942556965, 8305602914772423), + (2237, 16393440866577822357, 8246197619002928), (2239, 15110017253766555455, 8238831654180237), + (2243, 14104398611864414187, 8224139132282457), (2251, 6883725020842302691, 8194910739097979), + (2267, 13865572078341894995, 8137072815928342), (2269, 4089339915855400821, 8129900429135985), + (2273, 15021963607759076129, 8115593521209657), (2281, 16036779262676914009, 8087130238364555), + (2287, 14583171528319575567, 8065913455928968), (2293, 13072812524979512157, 8044807707679699), + (2297, 4946971854333950281, 8030798464827841), (2309, 9770622781354171341, 7989061963494825), + (2311, 191571552474698935, 7982148019779122), (2333, 13362622153694445877, 7906877014020382), + (2339, 9984428387052711563, 7886594302569282), (2341, 12907204952044530349, 7879856503079688), + (2347, 10532014085543587203, 7859712004137005), (2351, 17214868778272546255, 7846339461382199), + (2357, 1017427547552923933, 7826365750407107), (2371, 18298921156206185323, 7780153552808752), + (2377, 18058718325419489529, 7760514965801241), (2381, 17276874961937127301, 7747477561406783), + (2383, 10241310285152218543, 7740975272223899), (2389, 13551291690816351229, 7721533726960883), + (2393, 2227793162265800425, 7708626859051212), (2399, 3252593890445660831, 7689347258736786), + (2411, 9357265865676806979, 7651075932687495), (2417, 5975920814941902737, 7632082777703579), + (2423, 2047946411815051335, 7613183687044800), (2437, 499583548980234061, 7569447711821728), + (2441, 15590181492856536249, 7557043864690516), (2447, 5435268687022716271, 7538514129019023), + (2459, 7749282890663670931, 7501725934814783), (2467, 14722999222186504715, 7477399300247082), + (2473, 12524093530027633305, 7459257611690073), (2477, 11342103845078581797, 7447211979697033), + (2503, 16596910768675153911, 7369853804917919), (2521, 18227227087509120617, 7317232873347699), + (2531, 6646950057377760203, 7288322431335263), (2539, 3465575786986788547, 7265358043997460), + (2543, 3358569605240866063, 7253930032917637), (2549, 10949362017858984541, 7236855266265026), + (2551, 16769109959597197255, 7231181526346355), (2557, 13101011825520745301, 7214213560308780), + (2579, 13311124746480603163, 7152673157700485), (2591, 17656474451099840991, 7119546149637032), + (2593, 8330558160552983009, 7114054791249345), (2609, 14154994877564784337, 7070427011770621), + (2617, 2283815468048106505, 7048813172987983), (2621, 15624483725156506901, 7038055732052480), + (2633, 11910165182417864697, 7005979519069332), (2647, 13603341304072929639, 6968924848398017), + (2657, 5963776123190253985, 6942696301734870), (2659, 7978095406079723339, 6937474266156281), + (2663, 4419460277516595543, 6927053726515040), (2671, 3549841427887199375, 6906306279936185), + (2677, 15855793094361478621, 6890827072734236), (2683, 3417082297664423091, 6875417097916344), + (2687, 14849388697965671807, 6865182014778396), (2689, 8472193726675826049, 6860075892045203), + (2693, 575390457553509965, 6849886399446547), (2699, 12705630690265304355, 6834658789814580), + (2707, 16695427772659180443, 6814460315371094), (2711, 10390327628386014503, 6804405781523257), + (2713, 8540033378761222569, 6799389632771674), (2719, 7639218031260373343, 6784385462931059), + (2729, 2142769465506019737, 6759525127779242), (2731, 13509149815971843, 6754574907985921), + (2741, 5155128041029374877, 6729932168445659), (2749, 7414933503619154069, 6710347062098781), + (2753, 8831387101034939713, 6700597193501471), (2767, 16100067559815167023, 6666694641745410), + (2777, 11511777990543267177, 6642687819124793), (2789, 14842055826964587245, 6614106874761402), + (2791, 10931893478292941015, 6609367278290774), (2797, 5111271597112943333, 6595189157565088), + (2801, 3839504389493990929, 6585770822459675), (2803, 14017682795933408827, 6581071735180004), + (2819, 9318255963448883115, 6543719075455676), (2833, 8647114765226362353, 6511381600321055), + (2837, 12601265426453687357, 6502200942442563), (2843, 10822781960938280723, 6488478393847890), + (2851, 1067594799074737291, 6470271509543862), (2857, 17813989114233340185, 6456683259961341), + (2861, 1972982763563482277, 6447656090076739), (2879, 12129102650757964991, 6407344242344408), + (2887, 9181839706934750839, 6389589218465379), (2897, 7144372402727689649, 6367533335764429), + (2903, 2923011461903683687, 6354372743268877), (2909, 16893133795930644725, 6341266439913905), + (2917, 9106380344923467373, 6323875239530185), (2927, 5123745449923425167, 6302269926105074), + (2939, 12345949504248617907, 6276537622902195), (2953, 12487315070553807545, 6246780925739773), + (2957, 386776507463642949, 6238330765542628), (2963, 273930725360519835, 6225698303648178), + (2969, 15172431467833858217, 6213116899194864), (2971, 13150523038746829459, 6208934390343167), + (2999, 8051613201895899655, 6150965012907486), (3001, 12760893267917703817, 6146865735991186), + (3011, 3394053874737659115, 6126451037432597), (3019, 6091886002480431587, 6110216652437744), + (3023, 14938018356745280303, 6102131681676993), (3037, 15847071217750484085, 6074001999904363), + (3041, 16426761904506894369, 6066012520128099), (3049, 3817610859465636953, 6050096449232388), + (3061, 17295705812331399261, 6026378331822787), (3067, 4559058365788014387, 6014588873071259), + (3079, 17218558774875365815, 5991147799191150), (3083, 1352242672934920099, 5983374659004071), + (3089, 13579765627586766065, 5971752694629184), (3109, 5684136642847780781, 5933336787941316), + (3119, 3761503440487103183, 5914313585671545), (3121, 4604297863960186065, 5910523573761471), + (3137, 12819222850075493313, 5880377454163070), (3163, 17274503934975558611, 5832040491213895), + (3167, 14584984894401236895, 5824674478594743), (3169, 10111074299789678497, 5820998445474771), + (3181, 3635997653007195493, 5799039318990742), (3187, 11414176125935122619, 5788121767715579), + (3191, 11781405334446902599, 5780866209247744), (3203, 8730959730172863019, 5759208265285529), + (3209, 1965966492118624697, 5748440035434575), (3217, 17322851677549442161, 5734144878367905), + (3221, 10663718554873388733, 5727023928503431), (3229, 5541449907555981749, 5712834956243280), + (3251, 15479150363912536699, 5674175353340372), (3253, 9611814080829292957, 5670686773350615), + (3257, 10279656276875295113, 5663722466597958), (3259, 3792365305119791219, 5660246724059389), + (3271, 2227595203031266551, 5639481526661434), (3299, 7162861218072729803, 5591616875934995), + (3301, 14054396045252808941, 5588229043838095), (3307, 9131333549640924099, 5578090134172830), + (3313, 11926630185899746321, 5567987948599321), (3319, 17407412605862704327, 5557922287951055), + (3323, 9281659973289909811, 5551232041441333), (3329, 4327698144057422593, 5541226816974932), + (3331, 1030049353860695467, 5537899751939222), (3343, 7432774234904805871, 5518020961325022), + (3347, 16142967849386099995, 5511426373979549), (3359, 15481206175584169695, 5491736848380336), + (3361, 18139389813629892321, 5488468929993915), (3371, 2670427501622741379, 5472187503325289), + (3373, 306260796954561189, 5468942802760021), (3389, 6221489665461793301, 5443123066895707), + (3391, 9770083266405884607, 5439912731851828), (3407, 3021216082515388847, 5414365739274890), + (3413, 12685176777320925181, 5404847369970568), (3433, 445988860506231513, 5373359765135319), + (3449, 8824913807370472649, 5348432610527559), (3457, 1371366279127380609, 5336055560806928), + (3461, 4130663581948830541, 5329888492837200), (3463, 3861937468506908727, 5326810301388839), + (3467, 10822231740964876835, 5320664572745760), (3469, 13655589155746938181, 5317597023265941), + (3491, 1976248147684724235, 5284085956376268), (3499, 13986628187353941251, 5272004593800957), + (3511, 2553437089097932807, 5253985780036898), (3517, 14135335592450168213, 5245022483283921), + (3527, 8849416210013201399, 5230151424357684), (3529, 17944934090406599801, 5227187326072414), + (3533, 13136713300156589829, 5221269197200552), (3539, 10956500718546899547, 5212417087795860), + (3541, 16279603284479624061, 5209473051033479), (3547, 10453328330464110163, 5200660860927417), + (3557, 9894964209344341997, 5186039942004372), (3559, 14139566685327242711, 5183125617788578), + (3571, 16742060359253054267, 5165708225625749), (3581, 13120317552565827413, 5151282902460081), + (3583, 10631461488197104127, 5148407500337580), (3593, 16916788678784573497, 5134078506459658), + (3607, 1493332206687881639, 5114151392766717), (3613, 8536660971835696181, 5105658475978287), + (3617, 17268641258938496481, 5100012185156082), (3623, 12876570732103631255, 5091566125782376), + (3631, 2667182770227902671, 5080348133767433), (3637, 15180397308939424797, 5071967026040569), + (3643, 4501552424245893875, 5063613525585932), (3659, 720930418841340771, 5041471460428956), + (3671, 13738326967453531495, 5024991575513361), (3673, 8708590858647525865, 5022255397143901), + (3677, 10826237071271474677, 5016791970005317), (3691, 11394900159322074691, 4997763227772839), + (3697, 419130782307709585, 4989652170329876), (3701, 3982423268007006685, 4984259409270346), + (3709, 10165851951108741845, 4973508782342828), (3719, 3625859079828363063, 4960135540120879), + (3727, 11992610917788635247, 4949488616503770), (3733, 1319389410040302781, 4941533370937463), + (3739, 17015999013165082515, 4933603657049893), (3761, 13002477675991497297, 4904744502448697), + (3767, 783509172230827783, 4896932326442673), (3769, 9925708936450774921, 4894333795094070), + (3779, 10304598237523382763, 4881382395795065), (3793, 9454381882228148785, 4863365165755220), + (3797, 10522951715474029181, 4858241789230853), (3803, 6330002896710745427, 4850576932345398), + (3821, 16868077412599103205, 4827726792386692), (3823, 14620359545733701647, 4825201170209142), + (3833, 3157073861819323209, 4812612594236773), (3847, 15996448721054084791, 4795098537486236), + (3851, 15850500166165906595, 4790117910597131), (3853, 15722581764355610565, 4787631475138736), + (3863, 16379066055610603687, 4775237917087639), (3877, 7550937024755496109, 4757994344521421), + (3881, 4515435936620477721, 4753090459600502), (3889, 6147333586918894033, 4743312952869517), + (3907, 8753586770580370795, 4721459962556834), (3911, 10055857418856753783, 4716631059501291), + (3917, 18117085639918469509, 4709406197015458), (3919, 5671938404904314799, 4707002825646734), + (3923, 15126988448922668251, 4702203434542327), (3929, 10653006440123943145, 4695022670834703), + (3931, 4368842211300837587, 4692633954136238), (3943, 9408166962269822039, 4678352542153069), + (3947, 15553778636256748867, 4673611369067532), (3967, 9128046033953075327, 4650048922034169), + (3989, 3838254595432170429, 4624403127026711), (4001, 9935699444849808481, 4610533385081117), + (4003, 16838471857440594955, 4608229846042855), (4007, 10680420826305505303, 4603629666510993), + (4013, 14433784298890603557, 4596746592003376), (4019, 8147044222651021179, 4589884069099166), + (4021, 13845380157785482909, 4587601112586309), (4027, 1575783452037766515, 4580765848946995), + (4049, 715272615355001137, 4555876530923574), (4051, 9325828650446102619, 4553627270725636), + (4057, 2259805719653351529, 4546892796083202), (4073, 17463944303516825689, 4529031199044819), + (4079, 10862730881355808527, 4522369226209745), (4091, 1848732600885093171, 4509103904597788), + (4093, 7918624318961075541, 4506900579943696), (4099, 5944900932268923563, 4500303506638095), + (4111, 12196120260847132399, 4487167130554500), (4127, 250307164557241311, 4469770795665023), + (4129, 15189859493972505569, 4467605733521325), (4133, 14023631715363031981, 4463281895405166), + (4139, 13931993712108252803, 4456811808096050), (4153, 1159306574341004809, 4441787641153275), + (4157, 4406451013998937877, 4437513609263784), (4159, 7069995204013711295, 4435379676294674), + (4177, 13182554718703138993, 4416266237421487), (4201, 10204768680623898585, 4391036437445739), + (4211, 6965168149417759931, 4380608899004880), (4217, 12773178253552736713, 4374376114230389), + (4219, 7913867450441879219, 4372302458807668), (4229, 14778332684258207821, 4361963602201360), + (4231, 248514396644160823, 4359901695511593), (4241, 13549070452630335601, 4349621333107651), + (4243, 12334059141436247451, 4347571075585564), (4253, 17570599633810814389, 4337348712369986), + (4259, 15835007357004489483, 4331238336160965), (4261, 15078622297284761389, 4329205368155257), + (4271, 15401800366857471567, 4319069087733446), (4273, 14306695497372678225, 4317047524855968), + (4283, 11396237408133428339, 4306968030284742), (4289, 6829897316169449281, 4300942894313255), + (4297, 10826783466114845049, 4292935553574482), (4327, 3465958616114135767, 4263171729537682), + (4337, 4249088616471257105, 4253341958429686), (4339, 3804986389944698939, 4251381441278993), + (4349, 8788607431760448597, 4241605903359289), (4357, 1752800561513829325, 4233817781434370), + (4363, 4879106729557832355, 4227995432892402), (4373, 14042810661188908605, 4218327023487205), + (4391, 17963625064719208087, 4201034860785595), (4397, 15606524438071305893, 4195302268298738), + (4409, 3782231037113502985, 4183883890612282), (4421, 1969432979595319693, 4172527499142626), + (4423, 1259533508989438071, 4170640758243172), (4441, 1013511721230608105, 4153736562420525), + (4447, 10581885345633700511, 4148132240546334), (4451, 14928144721074321483, 4144404420065053), + (4457, 15160516836885368537, 4138825235294940), (4463, 8303721452852899215, 4133261051693827), + (4481, 14552385695283031681, 4116657905313446), (4483, 8295479824358343979, 4114821341447591), + (4493, 15778063092647631173, 4105663047787569), (4507, 8402743639522012307, 4092909712382860), + (4513, 662169851526910561, 4087468219301917), (4517, 3695882972483317293, 4083848588379356), + (4519, 2249204687898641943, 4082041175859604), (4523, 3597176270840553731, 4078431146077725), + (4547, 4819602366300186347, 4056904348737530), (4549, 1184095245003998477, 4055120702068487), + (4561, 12804733991967647537, 4044451671499572), (4567, 8667990536934683111, 4039138181237037), + (4583, 4512066355362951639, 4025036891492374), (4591, 9422264180537769231, 4018023104706937), + (4597, 13996572401370223197, 4012778784796508), (4603, 5570491910157783347, 4007548136804160), + (4621, 14482749945773264069, 3991937691778738), (4637, 16867413170698403893, 3978163483655283), + (4639, 13106373888110946783, 3976448388383175), (4643, 1326989558608440715, 3973022630564193), + (4649, 5773287293449644569, 3967895047044429), (4651, 16011504155142003843, 3966188792455289), + (4657, 2150865800305837777, 3961078821926036), (4663, 636913102266188679, 3955982001653345), + (4673, 5542313006524333505, 3947516386413342), (4679, 13912921529412482935, 3942454386345277), + (4691, 2355489170784911835, 3932369233363792), (4703, 18325151671777806751, 3922335546185318), + (4721, 2961794536723541649, 3907380655308102), (4723, 13908290418479719099, 3905726037202953), + (4729, 3237639581556127689, 3900770580188105), (4733, 18244075429755844309, 3897473922186678), + (4751, 1615206384900689007, 3882707656011271), (4759, 17136594988415618343, 3876180725721696), + (4783, 3089241480878392399, 3856730937426207), (4787, 11117371350042209403, 3853508266912377), + (4789, 7965727029532543901, 3851898950450939), (4793, 16872632175911261065, 3848684346695086), + (4799, 7976035414241991999, 3843872488791321), (4801, 15891633719821434177, 3842271208854311), + (4813, 13560062441883314693, 3832691475942146), (4817, 4702636853335131697, 3829508838220791), + (4831, 8923626764698659103, 3818411110269002), (4861, 4770120818895886933, 3794845520203569), + (4871, 11845907506171931319, 3787054829338852), (4877, 9005884281218462661, 3782395750196750), + (4889, 14832102874565810473, 3773111898897433), (4903, 17190123123144797335, 3762338175343575), + (4909, 5264593287281947813, 3757739676860776), (4919, 7211443149775049351, 3750100441900701), + (4931, 13205639136117363051, 3740974259523332), (4933, 8869993298771347341, 3739457545856385), + (4937, 15565958235988250361, 3736427805085993), (4943, 8564693030379004847, 3731892387964707), + (4951, 3968043312159295591, 3725862264938305), (4957, 9638302834558753013, 3721352445775580), + (4967, 16541533743568017495, 3713860292673555), (4969, 10357499691215465689, 3712365480722389), + (4973, 5515847262740016741, 3709379463846682), (4987, 7294361201795716019, 3698966126671255), + (4993, 964270018673781889, 3694521144343991), (4999, 13125638861809336887, 3690086832108331), + (5003, 9487002298951564323, 3687136532822216), (5009, 2938810495272553841, 3682719918887912), + (5011, 17154625301035025051, 3681250064599790), (5021, 14901412858587122357, 3673918357639823), + (5023, 8751461502617929823, 3672455519352887), (5039, 7526593731999769423, 3660794616731405), + (5051, 3031240859469199731, 3652097421047228), (5059, 14629044717082965227, 3646322212632842), + (5077, 14050336681708653949, 3633394538843717), (5081, 10953321564727753833, 3630534161328390), + (5087, 4587208817228736543, 3626252029429831), (5099, 15849222550876945603, 3617717998374103), + (5101, 7395332607476187621, 3616299563558037), (5107, 10818092520219327803, 3612050924948022), + (5113, 14341053724427042377, 3607812257717494), (5119, 4551325994353421311, 3603583526803975), + (5147, 12293050742728533523, 3583979808375665), (5153, 2233799398795800545, 3579806728839423), + (5167, 11445763789493482191, 3570107233154548), (5171, 5586463202364950267, 3567345595379917), + (5179, 3344563175364601075, 3561835117534186), (5189, 16850562133240176269, 3554970914185691), + (5197, 4678239116634440837, 3549498571042823), (5209, 4228337958151123945, 3541321572990891), + (5227, 12210777596142155843, 3529126472873455), (5231, 818131260772436623, 3526427848157054), + (5233, 5062014999015271569, 3525080082879715), (5237, 16544654747797167069, 3522387640578489), + (5261, 7296649765707959877, 3506318964780374), (5273, 10047230984201371561, 3498339479178750), + (5279, 6384201822820108127, 3494363340350360), (5281, 2997028292982919009, 3493039968511560), + (5297, 8566922866023314513, 3482488969928176), (5303, 12933244289280051463, 3478548759892429), + (5309, 6038885138464343701, 3474617455963373), (5323, 4168971091616116963, 3465478879148891), + (5333, 15983949815228171389, 3458980700114298), (5347, 6623854240045322443, 3449924083356938), + (5351, 13155069217954709207, 3447345182902177), (5381, 15004905930240978893, 3428125640904952), + (5387, 14803280978401037987, 3424307420402738), (5393, 17827633990761020401, 3420497695848238), + (5399, 7250229843380564647, 3416696438916382), (5407, 17075264303479989983, 3411641219476521), + (5413, 8267467416002100909, 3407859610882976), (5417, 6194319267136362265, 3405343192488379), + (5419, 9225074080042975619, 3404086376399621), (5431, 9948538647007047815, 3396564918746004), + (5437, 11023261264572803605, 3392816640373285), (5441, 6736570570568071873, 3390322380758969), + (5443, 1633534933589565291, 3389076625704492), (5449, 8693565568230157561, 3385344847441650), + (5471, 7279568717810075295, 3371731689583175), (5477, 14122183293968258157, 3368037990452720), + (5479, 17918155130549778007, 3366808555157793), (5483, 9891195983349641027, 3364352375288993), + (5501, 10026497869549456341, 3353343769080085), (5503, 305043378285947519, 3352125036109313), + (5507, 2599359615253061931, 3349690225841574), (5519, 8001722288903907695, 3342406971137806), + (5521, 12486050100244990833, 3341196173466682), (5527, 15569759562846943783, 3337569038123674), + (5531, 2498031334516082835, 3335155319781151), (5557, 15827618453022699677, 3319550850046707), + (5563, 1369495830027331443, 3315970532753829), (5569, 14359245027748411969, 3312397930276450), + (5573, 15080453256741560589, 3310020468995074), (5581, 13835884374224723717, 3305275770240019), + (5591, 16546310414890610151, 3299363991005106), (5623, 13912972010777557959, 3280587599806073), + (5639, 843990064021469111, 3271279317912670), (5641, 4133431042221037625, 3270119495428036), + (5647, 7993480210442229999, 3266644957271038), (5651, 5957407172981761051, 3264332697524252), + (5653, 3899497464723671357, 3263177794747842), (5657, 3759783616225404457, 3260870439050654), + (5659, 6816070305376687123, 3259717984398224), (5669, 14714442882574456237, 3253967908574625), + (5683, 2054687488766170363, 3245951798998689), (5689, 17999275154361350153, 3242528401073923), + (5693, 14694534406160691477, 3240250144688134), (5701, 11150233306087197837, 3235703222892396), + (5711, 16615312820024852655, 3230037484452731), (5717, 10486604554758797053, 3226647555310399), + (5737, 2205763715280591321, 3215399001866751), (5741, 2609084861148259173, 3213158695995393), + (5743, 346900289040681103, 3212039713339639), (5749, 2717758258902763997, 3208687436721090), + (5779, 4197520065223751579, 3192030467850761), (5783, 10344594679412082983, 3189822596180105), + (5791, 8043175407721743711, 3185416003058116), (5801, 10566890287353359769, 3179924853251086), + (5807, 10819633255563067471, 3176639241210530), (5813, 13007604327909074845, 3173360411785575), + (5821, 1191543681792611477, 3168999153703753), (5827, 819925641855289835, 3165736068939342), + (5839, 14295515830370906159, 3159230017761526), (5843, 14490938781161533787, 3157067272584212), + (5849, 649688712460962153, 3153828701266806), (5851, 1588986329370981715, 3152750653513852), + (5857, 16739703730880359713, 3149520927729136), (5861, 13656444725443737325, 3147371450897381), + (5867, 5499123126797001155, 3144152731158948), (5869, 2618186712114509541, 3143081287052232), + (5879, 15525512787330304711, 3137735001481468), (5881, 9798950601303968585, 3136667926153639), + (5897, 6043600059421206329, 3128157380652798), (5903, 9878054890224613359, 3124977820381086), + (5923, 2229928880090501259, 3114425810182264), (5927, 13031300394233489559, 3112323953721874), + (5939, 8684474899830258683, 3106035371899234), (5953, 167331459764877505, 3098730736386620), + (5981, 1761091935477036277, 3084224055126158), (5987, 4159529731001819723, 3081133134075422), + (6007, 5008596568040665671, 3070874658516655), (6011, 1224463630911680435, 3068831155167118), + (6029, 6296798690279359301, 3059668945713974), (6037, 9414347936243022781, 3055614390211951), + (6043, 12027167243159959187, 3052580518568517), (6047, 9465891658792911967, 3050561282240706), + (6053, 5250906994713622573, 3047537431638782), (6067, 12578569347772608379, 3040505039345566), + (6073, 2019938219828231817, 3037501082448468), (6079, 12930017519012403263, 3034503055388970), + (6089, 13023904216271532665, 3029519473429060), (6091, 3534288349042693603, 3028524720687826), + (6101, 4934451127404358013, 3023560739831101), (6113, 14047046239672495137, 3017625400574112), + (6121, 12365134934558126169, 3013681436645899), (6131, 13226535140764506427, 3008765955587922), + (6133, 12392073305671507037, 3007784782929977), (6143, 9690321199065720831, 3002888502964276), + (6151, 17867940365983012279, 2998982941588286), (6163, 5827650610337903131, 2993143610856652), + (6173, 16486422655865154101, 2988294844274996), (6197, 10207178542641609245, 2976721651397378), + (6199, 14244969169357577607, 2975761263705364), (6203, 16347211377266065651, 2973842346237232), + (6211, 13388813763368645739, 2970011926213097), (6217, 2222392039763302905, 2967145580458348), + (6221, 5610229832415764613, 2965237754976619), (6229, 9361078506501186813, 2961429454761526), + (6247, 17153375432076002135, 2952896442085729), (6257, 17739181571281823889, 2948177093448865), + (6263, 3572712847103574343, 2945352718139797), (6269, 15030462390893027541, 2942533749195972), + (6271, 15458083257430026111, 2941595291613706), (6277, 13198076730130571341, 2938783507043102), + (6287, 11343265880222860911, 2934109125768975), (6299, 12282210612023790995, 2928519459233140), + (6301, 3940536029711642037, 2927589918062141), (6311, 14059394548335120151, 2922951049549921), + (6317, 17115144374863334181, 2920174778171529), (6323, 9411544580387001979, 2917403775693429), + (6329, 17248827844558876041, 2914638027130597), (6337, 14927395235913299777, 2910958509343467), + (6343, 6293355537680509175, 2908204961959569), (6353, 3205604510841389105, 2903627274312852), + (6359, 12865436384164469479, 2900887572528628), (6361, 17086655570240005993, 2899975487141888), + (6367, 14680328603971461919, 2897242669029299), (6373, 10177114728254006509, 2894514996659273), + (6379, 9323138876569931715, 2891792455511765), (6389, 11153509525237125981, 2887266250384966), + (6397, 15969684020666483797, 2883655475021033), (6421, 14505156646653095485, 2872877133423072), + (6427, 10054293525782567187, 2870195125830022), (6449, 12242528242437103569, 2860403794961940), + (6451, 8564253371688126971, 2859516985538606), (6469, 15991550589791801741, 2851560376211091), + (6473, 5639750737196230905, 2849798250225483), (6481, 5610018912094048177, 2846280523639801), + (6491, 9128168535627034323, 2841895559037059), (6521, 8557184607111086281, 2828821357722673), + (6529, 14697497728815605377, 2825355195850750), (6547, 518436063779220635, 2817587303147938), + (6551, 13597821268805285415, 2815866901802709), (6553, 17436156385252092585, 2815007488739440), + (6563, 17465803393879499275, 2810718280315336), (6569, 10626043473118730905, 2808151023551461), + (6571, 18101446627192084739, 2807296313150137), (6577, 7505471665082371921, 2804735300852904), + (6581, 1345454665762131101, 2803030553671106), (6599, 7161775771608406007, 2795384766435755), + (6607, 3696608014770916655, 2792000011156281), (6619, 15353242650259241555, 2786938219324603), + (6637, 8357595213145189349, 2779379851395141), (6653, 1186713732684155733, 2772695637112513), + (6659, 12391092692852203691, 2770197337995127), (6661, 4536220806596043469, 2769365571792456), + (6673, 10526779774117484273, 2764385444883793), (6679, 13467034601498394023, 2761902092185888), + (6689, 17961376013166438881, 2757773071267685), (6691, 8973868175149393291, 2756948748125773), + (6701, 16605097784303240613, 2752834513312871), (6703, 14324228390818770127, 2752013139446449), + (6709, 9246743228481923101, 2749551956134975), (6719, 4530008590805292479, 2745459752003207), + (6733, 3843870776090078853, 2739751087733484), (6737, 5292794462591741617, 2738124398650668), + (6761, 3486901187132200409, 2728404684766979), (6763, 8150062293692760643, 2727597822521004), + (6779, 5891311538513228979, 2721160063978396), (6781, 6999479796734209749, 2720357480269805), + (6791, 11036536765054028599, 2716351652732962), (6793, 12073343758532705209, 2715551902503982), + (6803, 4238168600206971803, 2711560204866904), (6823, 627237963520535831, 2703611911726447), + (6827, 1680661317393780739, 2702027841469100), (6829, 6950281520230586661, 2701236502227200), + (6833, 3018214528670756433, 2699655213480104), (6841, 9284043245984795529, 2696498183556432), + (6857, 14225810509227958137, 2690206223378963), (6863, 14941782064075680815, 2687854301866465), + (6869, 9963229074605100669, 2685506489111886), (6871, 15958004187764455655, 2684724796057277), + (6883, 2355758832019569355, 2680044177496665), (6899, 17246194995713379899, 2673828681505950), + (6907, 17672231871396569139, 2670731732113732), (6911, 16193951135175206143, 2669185946130741), + (6917, 370695016082930125, 2666870619301655), (6947, 6718045560167722123, 2655353976350878), + (6949, 5802933162344089773, 2654589735747525), (6959, 7962928466363485135, 2650775121958550), + (6961, 12534563923092397521, 2650013514395855), (6967, 977012855346465415, 2647731315302074), + (6971, 3191331710356293107, 2646212031804554), (6977, 14766384642635494593, 2643936372898029), + (6983, 2826581148341575287, 2641664624618294), (6991, 16045580133346843567, 2638641692706272), + (6997, 9506782782592059901, 2636379030114270), (7001, 5401489123140205801, 2634872742995222), + (7013, 5523764801766727277, 2630364191317489), (7019, 1952689962496964931, 2628115696496588), + (7027, 4502087104939786683, 2625123676349729), (7039, 9670192588718318719, 2620648398026644), + (7043, 12207904888195402539, 2619160027503840), (7057, 13242341714242962801, 2613964017813454), + (7069, 10281535104033899189, 2609526676150735), (7079, 16080641005630970903, 2605840383346454), + (7103, 17083300368416363583, 2597035629129881), (7109, 12639483806870055693, 2594843729597629), + (7121, 11885081001289063729, 2590471011614878), (7127, 16831651004817344487, 2588290174506742), + (7129, 16953719619995087977, 2587564044565794), (7151, 7261583634106053391, 2579603422417780), + (7159, 5158595004269663687, 2576720781353478), (7177, 17238722656035942969, 2570258335475763), + (7187, 10628630472969424411, 2566682075095248), (7193, 9324671409983029289, 2564541091854518), + (7207, 6974799167595189143, 2559559327557867), (7211, 12552790621230449283, 2558139519305165), + (7213, 5431981756905460645, 2557430205699369), (7219, 9740821223019921147, 2555304623037754), + (7229, 13549897777202617109, 2551769826215182), (7237, 779978400795235981, 2548949022206653), + (7243, 1319261829377543523, 2546837508450856), (7247, 6600304592676813487, 2545431775039264), + (7253, 4702609925863637245, 2543326082132848), (7283, 11559925848195852475, 2532849659990327), + (7297, 1266523061659378561, 2527990143032691), (7307, 7389300657417251619, 2524530460340707), + (7309, 9509827838245668421, 2523839659831652), (7321, 7339894206626953129, 2519702782913475), + (7331, 7936302115465819915, 2516265730965700), (7333, 4512949525192272685, 2515579445480642), + (7349, 8313459841083961757, 2510102609022935), (7351, 7613579311608594695, 2509419680820235), + (7369, 10356110765766917497, 2503290008645616), (7393, 13329163646930396961, 2495163543042006), + (7411, 12017390418009676859, 2489103234881871), (7417, 16529197939041887561, 2487089668829655), + (7433, 16411720511158518073, 2481736051891504), (7451, 4867306247337669907, 2475740715838082), + (7457, 13959363927577175777, 2473748702388299), (7459, 7204097799532903051, 2473085410069654), + (7477, 16714817587184995613, 2467131747185977), (7481, 8879391178910318857, 2465812601752379), + (7487, 8327767459481539263, 2463836526473828), (7489, 2943498353329271489, 2463178538350854), + (7499, 7741285984793166947, 2459893862342919), (7507, 6275873766385266395, 2457272422233855), + (7517, 15651634122937278197, 2454003468632373), (7523, 10828236319221238859, 2452046267939592), + (7529, 4687026353168597721, 2450092186706010), (7537, 14956621073960338321, 2447491584676867), + (7541, 1223096676416228061, 2446193352832456), (7547, 11989039311189260723, 2444248585359686), + (7549, 8528167547654833109, 2443601016520009), (7559, 8011729169729919031, 2440368312436770), + (7561, 7380161463162464441, 2439722797739657), (7573, 10532645104281011645, 2435856869630206), + (7577, 8104686686205503145, 2434570948094173), (7583, 11637771811766648415, 2432644609482995), + (7589, 3417594171516092973, 2430721316867775), (7591, 14242704125413210647, 2430080894968983), + (7603, 2938183226787092859, 2426245439130547), (7607, 6697766153751252999, 2424969642922249), + (7621, 10459044894698723597, 2420514902730553), (7639, 12602900552518673895, 2414811372392924), + (7643, 8312257829367486035, 2413547569502754), (7649, 8303325904795657761, 2411654343536351), + (7669, 1820861294014621277, 2405364985488271), (7673, 17468270877045953609, 2404111048313508), + (7681, 13079152223072805377, 2401607092007492), (7687, 12399418060212989879, 2399732545038318), + (7691, 16966879154521046435, 2398484471942471), (7699, 12504683377151597595, 2395992216354013), + (7703, 16902131594475141543, 2394748029820790), (7717, 12155201971596873133, 2390403534237339), + (7723, 5099546626617880707, 2388546429329218), (7727, 11158286760776296655, 2387309961655176), + (7741, 15213023403508820245, 2382992387767672), (7753, 6999912429363278841, 2379304020857674), + (7757, 9407673012194790021, 2378077101161473), (7759, 4426838183431780527, 2377464115699130), + (7789, 8521168978971237221, 2368307109219354), (7793, 10912291823405752977, 2367091501823373), + (7817, 15223224513176451001, 2359823982820717), (7823, 5647443698905071727, 2358014070524038), + (7829, 13225389511525317821, 2356206932393607), (7841, 3761808924099167585, 2352600953157703), + (7853, 14765851680547337509, 2349005994360060), (7867, 16228538926419703411, 2344825737092862), + (7873, 17809437533883691329, 2343038749359780), (7877, 3187256402731839501, 2341848936614136), + (7879, 15749618908978823927, 2341254483273201), (7883, 13069271299209418467, 2340066481505715), + (7901, 7641588830939294069, 2334735359284843), (7907, 12420698804657854155, 2332963712369995), + (7919, 12818844884155027471, 2329428472497733), (7927, 7937661667140567751, 2327077592242910), ]; pub const NEXT_PRIME: u64 = 7933; diff --git a/src/factor/sieve.rs b/src/factor/sieve.rs new file mode 100644 index 000000000..d0d5893fe --- /dev/null +++ b/src/factor/sieve.rs @@ -0,0 +1,53 @@ +/* +* This file is part of the uutils coreutils package. +* +* (c) kwantam +* +* For the full copyright and license information, please view the LICENSE file +* that was distributed with this source code. +*/ + +use std::iter::repeat; + +// A lazy Sieve of Eratosthenes +// Not particularly efficient, but fine for generating a few thousand primes. +pub struct Sieve { + inner: Box>, + filts: Vec, +} + +impl Iterator for Sieve { + type Item = u64; + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } + + #[inline] + fn next(&mut self) -> Option { + while let Some(n) = self.inner.next() { + if self.filts.iter().all(|&x| n % x != 0) { + self.filts.push(n); + return Some(n); + } + } + None + } +} + +impl Sieve { + #[inline] + pub fn new() -> Sieve { + fn next(s: &mut u64, t: u64) -> Option { + let ret = Some(*s); + *s = *s + t; + ret + } + let next = next; + + let odds_by_3 = Box::new(repeat(2).scan(3, next)) as Box>; + + Sieve { inner: odds_by_3, filts: Vec::new() } + } +} diff --git a/test/factor.rs b/test/factor.rs new file mode 100644 index 000000000..69d0860fb --- /dev/null +++ b/test/factor.rs @@ -0,0 +1,89 @@ +/* +* This file is part of the uutils coreutils package. +* +* (c) kwantam +* +* For the full copyright and license information, please view the LICENSE file +* that was distributed with this source code. +*/ + +extern crate libc; +extern crate rand; + +use rand::{weak_rng, Rng}; +use sieve::Sieve; +use std::io::Write; +use std::process::{Command, Stdio}; + +#[path="../src/factor/sieve.rs"] +mod sieve; + +const NUM_PRIMES: usize = 10000; +const LOG_PRIMES: f64 = 14.0; // ceil(log2(NUM_PRIMES)) + +const NUM_TESTS: usize = 1000; +const PROGNAME: &'static str = "./factor"; + +#[test] +fn test_random() { + + let mut primes = Sieve::new().take(NUM_PRIMES - 1).collect::>(); + primes.push(2); + let primes = primes; + + let mut rng = weak_rng(); + let mut rand_gt = move |min: u64| { + let mut product = 1u64; + let mut factors = Vec::new(); + while product < min { + // log distribution---higher probability for lower numbers + let mut factor; + loop { + let next = rng.gen_range(0f64, LOG_PRIMES).exp2().floor() as usize; + if next < NUM_PRIMES { + factor = primes[next]; + break; + } + } + let factor = factor; + + match product.checked_mul(factor) { + Some(p) => { + product = p; + factors.push(factor); + }, + None => break, + }; + } + + factors.sort(); + (product, factors) + }; + + // build an input and expected output string from factor + let mut instring = String::new(); + let mut outstring = String::new(); + for _ in 0..NUM_TESTS { + let (product, factors) = rand_gt(1 << 63); + instring.push_str(&(format!("{} ", product))[..]); + + outstring.push_str(&(format!("{}:", product))[..]); + for factor in factors.iter() { + outstring.push_str(&(format!(" {}", factor))[..]); + } + outstring.push_str("\n"); + } + + // now run factor + let mut process = Command::new(PROGNAME) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .unwrap_or_else(|e| panic!("{}", e)); + + process.stdin.take().unwrap_or_else(|| panic!("Could not take child process stdin")) + .write_all(instring.as_bytes()).unwrap_or_else(|e| panic!("{}", e)); + + let output = process.wait_with_output().unwrap_or_else(|e| panic!("{}", e)); + assert_eq!(&output.stdout[..], outstring.as_bytes()); +} From 4390e4ffa6b2afe382a5dadee6e49612dc206680 Mon Sep 17 00:00:00 2001 From: kwantam Date: Thu, 30 Apr 2015 18:44:31 -0400 Subject: [PATCH 07/11] fix `tac` --- src/tac/tac.rs | 106 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/src/tac/tac.rs b/src/tac/tac.rs index cefb42c9a..3ad69a7a2 100644 --- a/src/tac/tac.rs +++ b/src/tac/tac.rs @@ -1,5 +1,5 @@ #![crate_name = "tac"] -#![feature(collections, core, old_io, old_path, rustc_private)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -13,7 +13,8 @@ extern crate getopts; extern crate libc; -use std::old_io as io; +use std::fs::File; +use std::io::{stdin, stdout, BufReader, Read, Stdout, Write}; #[path = "../common/util.rs"] #[macro_use] @@ -23,8 +24,6 @@ static NAME: &'static str = "tac"; static VERSION: &'static str = "1.0.0"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].clone(); - let opts = [ getopts::optflag("b", "before", "attach the separator before instead of after"), getopts::optflag("r", "regex", "interpret the sequence as a regular expression (NOT IMPLEMENTED)"), @@ -32,7 +31,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("V", "version", "output version information and exit") ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => crash!(1, "{}", f) }; @@ -40,7 +39,7 @@ pub fn uumain(args: Vec) -> i32 { println!("tac {}", VERSION); println!(""); println!("Usage:"); - println!(" {0} [OPTION]... [FILE]...", program); + println!(" {0} [OPTION]... [FILE]...", &args[0][..]); println!(""); print!("{}", getopts::usage("Write each file to standard output, last line first.", &opts)); } else if matches.opt_present("version") { @@ -63,41 +62,86 @@ pub fn uumain(args: Vec) -> i32 { } else { matches.free }; - tac(files, before, regex, separator.as_slice()); + tac(files, before, regex, &separator[..]); } 0 } fn tac(filenames: Vec, before: bool, _: bool, separator: &str) { - for filename in filenames.into_iter() { - let mut file = io::BufferedReader::new( - if filename.as_slice() == "-" { - Box::new(io::stdio::stdin_raw()) as Box + let mut out = stdout(); + let sbytes = separator.as_bytes(); + let slen = sbytes.len(); + + for filename in filenames.iter() { + let mut file = BufReader::new( + if filename == "-" { + Box::new(stdin()) as Box } else { - let r = crash_if_err!(1, io::File::open(&Path::new(filename))); - Box::new(r) as Box + match File::open(filename) { + Ok(f) => Box::new(f) as Box, + Err(e) => { + show_warning!("failed to open '{}' for reading: {}", filename, e); + continue; + }, + } + }); + + let mut data = Vec::new(); + match file.read_to_end(&mut data) { + Err(e) => { + show_warning!("failed to read '{}': {}", filename, e); + continue; + }, + Ok(_) => (), + }; + + // find offsets in string of all separators + let mut offsets = Vec::new(); + let mut i = 0; + loop { + if i + slen > data.len() { + break; + } + + if &data[i..i+slen] == sbytes { + offsets.push(i); + i += slen; + } else { + i += 1; } - ); - let mut data = crash_if_err!(1, file.read_to_string()); - if data.as_slice().ends_with("\n") { - // removes blank line that is inserted otherwise - let mut buf = data.to_string(); - let len = buf.len(); - buf.truncate(len - 1); - data = buf.to_string(); } - let split_vec: Vec<&str> = data.as_slice().split_str(separator).collect(); - let rev: String = split_vec.iter().rev().fold(String::new(), |mut a, &b| { - if before { - a.push_str(separator); - a.push_str(b); + drop(i); + + // if there isn't a separator at the end of the file, fake it + if offsets.len() == 0 || *offsets.last().unwrap() < data.len() - slen { + offsets.push(data.len()); + } + + let mut prev = *offsets.last().unwrap(); + let mut start = true; + for off in offsets.iter().rev().skip(1) { + // correctly handle case of no final separator in file + if start && prev == data.len() { + show_line(&mut out, &[], &data[*off+slen..prev], before); + start = false; } else { - a.push_str(b); - a.push_str(separator); + show_line(&mut out, sbytes, &data[*off+slen..prev], before); } - a - }); - print!("{}", rev); + prev = *off; + } + show_line(&mut out, sbytes, &data[0..prev], before); + } +} + +fn show_line(out: &mut Stdout, sep: &[u8], dat: &[u8], before: bool) { + if before { + out.write_all(sep).unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e)); + } + + out.write_all(dat).unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e)); + + if !before { + out.write_all(sep).unwrap_or_else(|e| crash!(1, "failed to write to stdout: {}", e)); } } From d89fbedf124088b705f86922d51fda0d2f1df4f7 Mon Sep 17 00:00:00 2001 From: kwantam Date: Thu, 30 Apr 2015 20:43:26 -0400 Subject: [PATCH 08/11] fix `shuf` --- src/shuf/deps.mk | 1 + src/shuf/shuf.rs | 251 ++++++++++++++++++++++++++++++----------------- 2 files changed, 160 insertions(+), 92 deletions(-) create mode 100644 src/shuf/deps.mk diff --git a/src/shuf/deps.mk b/src/shuf/deps.mk new file mode 100644 index 000000000..ea0f8a6b8 --- /dev/null +++ b/src/shuf/deps.mk @@ -0,0 +1 @@ +DEPLIBS += rand diff --git a/src/shuf/shuf.rs b/src/shuf/shuf.rs index c2265f97a..2af249287 100644 --- a/src/shuf/shuf.rs +++ b/src/shuf/shuf.rs @@ -1,5 +1,5 @@ #![crate_name = "shuf"] -#![feature(collections, core, old_io, old_path, rand, rustc_private)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -12,13 +12,13 @@ extern crate getopts; extern crate libc; +extern crate rand; -use std::cmp; -use std::old_io as io; -use std::old_io::IoResult; -use std::iter::{range_inclusive, RangeInclusive}; -use std::rand::{self, Rng}; -use std::usize; +use rand::read::ReadRng; +use rand::{Rng, ThreadRng}; +use std::fs::File; +use std::io::{stdin, stdout, BufReader, BufWriter, Read, Write}; +use std::usize::MAX as MAX_USIZE; #[path = "../common/util.rs"] #[macro_use] @@ -27,15 +27,13 @@ mod util; enum Mode { Default, Echo, - InputRange(RangeInclusive) + InputRange((usize, usize)) } static NAME: &'static str = "shuf"; static VERSION: &'static str = "0.0.1"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].clone(); - let opts = [ getopts::optflag("e", "echo", "treat each ARG as an input line"), getopts::optopt("i", "input-range", "treat each number LO through HI as an input line", "LO-HI"), @@ -47,7 +45,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("V", "version", "output version information and exit") ]; - let mut matches = match getopts::getopts(args.tail(), &opts) { + let mut matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => { crash!(1, "{}", f) @@ -62,7 +60,7 @@ Usage: {prog} -i LO-HI [OPTION]...\n {usage} With no FILE, or when FILE is -, read standard input.", - name = NAME, version = VERSION, prog = program, + name = NAME, version = VERSION, prog = &args[0][..], usage = getopts::usage("Write a random permutation of the input lines to standard output.", &opts)); } else if matches.opt_present("version") { println!("{} v{}", NAME, VERSION); @@ -76,10 +74,9 @@ With no FILE, or when FILE is -, read standard input.", } match parse_range(range) { Ok(m) => Mode::InputRange(m), - Err((msg, code)) => { - show_error!("{}", msg); - return code; - } + Err(msg) => { + crash!(1, "{}", msg); + }, } } None => { @@ -88,13 +85,19 @@ With no FILE, or when FILE is -, read standard input.", } else { if matches.free.len() == 0 { matches.free.push("-".to_string()); + } else if matches.free.len() > 1 { + show_error!("extra operand '{}'", &matches.free[1][..]); } Mode::Default } } }; let repeat = matches.opt_present("repeat"); - let zero = matches.opt_present("zero-terminated"); + let sep = if matches.opt_present("zero-terminated") { + 0x00 as u8 + } else { + 0x0a as u8 + }; let count = match matches.opt_str("head-count") { Some(cnt) => match cnt.parse::() { Ok(val) => val, @@ -103,102 +106,166 @@ With no FILE, or when FILE is -, read standard input.", return 1; } }, - None => usize::MAX + None => MAX_USIZE, }; let output = matches.opt_str("output"); let random = matches.opt_str("random-source"); - match shuf(matches.free, mode, repeat, zero, count, output, random) { - Err(f) => { - show_error!("{}", f); - return 1; + + match mode { + Mode::Echo => { + // XXX: this doesn't correctly handle non-UTF-8 cmdline args + let mut evec = matches.free.iter().map(|a| a.as_bytes()).collect::>(); + find_seps(&mut evec, sep); + shuf_bytes(&mut evec, repeat, count, sep, output, random); }, - _ => {} + Mode::InputRange((b, e)) => { + let rvec = (b..e).map(|x| format!("{}", x)).collect::>(); + let mut rvec = rvec.iter().map(|a| a.as_bytes()).collect::>(); + shuf_bytes(&mut rvec, repeat, count, sep, output, random); + }, + Mode::Default => { + let fdata = read_input_file(&matches.free[0][..]); + let mut fdata = vec!(&fdata[..]); + find_seps(&mut fdata, sep); + shuf_bytes(&mut fdata, repeat, count, sep, output, random); + } } } 0 } -fn shuf(input: Vec, mode: Mode, repeat: bool, zero: bool, count: usize, output: Option, random: Option) -> IoResult<()> { - match mode { - Mode::Echo => shuf_lines(input, repeat, zero, count, output, random), - Mode::InputRange(range) => shuf_lines(range.map(|num| num.to_string()).collect(), repeat, zero, count, output, random), - Mode::Default => { - let lines: Vec = input.into_iter().flat_map(|filename| { - let slice = filename.as_slice(); - let mut file_buf; - let mut stdin_buf; - let mut file = io::BufferedReader::new( - if slice == "-" { - stdin_buf = io::stdio::stdin_raw(); - &mut stdin_buf as &mut Reader - } else { - file_buf = crash_if_err!(1, io::File::open(&Path::new(slice))); - &mut file_buf as &mut Reader - } - ); - let mut lines = vec!(); - for line in file.lines() { - let mut line = crash_if_err!(1, line); - line.pop(); - lines.push(line); +fn read_input_file(filename: &str) -> Vec { + let mut file = BufReader::new( + if filename == "-" { + Box::new(stdin()) as Box + } else { + match File::open(filename) { + Ok(f) => Box::new(f) as Box, + Err(e) => crash!(1, "failed to open '{}': {}", filename, e), + } + }); + + let mut data = Vec::new(); + match file.read_to_end(&mut data) { + Err(e) => crash!(1, "failed reading '{}': {}", filename, e), + Ok(_) => (), + }; + + data +} + +fn find_seps(data: &mut Vec<&[u8]>, sep: u8) { + // need to use for loop so we don't borrow the vector as we modify it in place + // basic idea: + // * We don't care about the order of the result. This lets us slice the slices + // without making a new vector. + // * Starting from the end of the vector, we examine each element. + // * If that element contains the separator, we remove it from the vector, + // and then sub-slice it into slices that do not contain the separator. + // * We maintain the invariant throughout that each element in the vector past + // the ith element does not have any separators remaining. + for i in (0..data.len()).rev() { + if data[i].contains(&sep) { + let this = data.swap_remove(i); + let mut p = 0; + let mut i = 1; + loop { + if i == this.len() { + break; } - lines.into_iter() - }).collect(); - shuf_lines(lines, repeat, zero, count, output, random) + + if this[i] == sep { + data.push(&this[p..i]); + p = i + 1; + } + i += 1; + } + if p < this.len() { + data.push(&this[p..i]); + } } } } +fn shuf_bytes(input: &mut Vec<&[u8]>, repeat: bool, count: usize, sep: u8, output: Option, random: Option) { + let mut output = BufWriter::new( + match output { + None => Box::new(stdout()) as Box, + Some(s) => match File::create(&s[..]) { + Ok(f) => Box::new(f) as Box, + Err(e) => crash!(1, "failed to open '{}' for writing: {}", &s[..], e), + }, + }); + + let mut rng = match random { + Some(r) => WrappedRng::RngFile(rand::read::ReadRng::new(match File::open(&r[..]) { + Ok(f) => f, + Err(e) => crash!(1, "failed to open random source '{}': {}", &r[..], e), + })), + None => WrappedRng::RngDefault(rand::thread_rng()), + }; + + // we're generating a random usize. To keep things fair, we take this number mod ceil(log2(length+1)) + let mut len_mod = 1; + let mut len = input.len(); + while len > 0 { + len >>= 1; + len_mod <<= 1; + } + drop(len); + + let mut count = count; + while count > 0 && input.len() > 0 { + let mut r = input.len(); + while r >= input.len() { + r = rng.next_usize() % len_mod; + } + + // write the randomly chosen value and the separator + output.write_all(input[r]).unwrap_or_else(|e| crash!(1, "write failed: {}", e)); + output.write_all(&[sep]).unwrap_or_else(|e| crash!(1, "write failed: {}", e)); + + // if we do not allow repeats, remove the chosen value from the input vector + if !repeat { + // shrink the mask if we will drop below a power of 2 + if input.len() % 2 == 0 && len_mod > 2 { + len_mod >>= 1; + } + input.swap_remove(r); + } + + count -= 1; + } +} + +fn parse_range(input_range: String) -> Result<(usize, usize), String> { + let split: Vec<&str> = input_range.split('-').collect(); + if split.len() != 2 { + Err("invalid range format".to_string()) + } else { + let begin = match split[0].parse::() { + Ok(m) => m, + Err(e)=> return Err(format!("{} is not a valid number: {}", split[0], e)), + }; + let end = match split[1].parse::() { + Ok(m) => m, + Err(e)=> return Err(format!("{} is not a valid number: {}", split[1], e)), + }; + Ok((begin, end + 1)) + } +} + enum WrappedRng { - RngFile(rand::reader::ReaderRng), + RngFile(rand::read::ReadRng), RngDefault(rand::ThreadRng), } impl WrappedRng { - fn next_u32(&mut self) -> u32 { + fn next_usize(&mut self) -> usize { match self { - &mut WrappedRng::RngFile(ref mut r) => r.next_u32(), - &mut WrappedRng::RngDefault(ref mut r) => r.next_u32(), + &mut WrappedRng::RngFile(ref mut r) => r.next_u32() as usize, + &mut WrappedRng::RngDefault(ref mut r) => r.next_u32() as usize, } } } - -fn shuf_lines(mut lines: Vec, repeat: bool, zero: bool, count: usize, outname: Option, random: Option) -> IoResult<()> { - let mut output = match outname { - Some(name) => Box::new(io::BufferedWriter::new(try!(io::File::create(&Path::new(name))))) as Box, - None => Box::new(io::stdout()) as Box - }; - let mut rng = match random { - Some(name) => WrappedRng::RngFile(rand::reader::ReaderRng::new(try!(io::File::open(&Path::new(name))))), - None => WrappedRng::RngDefault(rand::thread_rng()), - }; - let mut len = lines.len(); - let max = if repeat { count } else { cmp::min(count, len) }; - for _ in range(0, max) { - let idx = rng.next_u32() as usize % len; - try!(write!(output, "{}{}", lines[idx], if zero { '\0' } else { '\n' })); - if !repeat { - lines.remove(idx); - len -= 1; - } - } - Ok(()) -} - -fn parse_range(input_range: String) -> Result, (String, i32)> { - let split: Vec<&str> = input_range.as_slice().split('-').collect(); - if split.len() != 2 { - Err(("invalid range format".to_string(), 1)) - } else { - let begin = match split[0].parse::() { - Ok(m) => m, - Err(e)=> return Err((format!("{} is not a valid number: {}", split[0], e), 1)) - }; - let end = match split[1].parse::() { - Ok(m) => m, - Err(e)=> return Err((format!("{} is not a valid number: {}", split[1], e), 1)) - }; - Ok(range_inclusive(begin, end)) - } -} From d8f58305d63929631109ad325dff7a15522c0f17 Mon Sep 17 00:00:00 2001 From: Camille TJHOA Date: Wed, 29 Apr 2015 22:54:54 +0200 Subject: [PATCH 09/11] new io cksum (includes BufReader fix) closes kwantam/coreutils#1 via cherry-pick --- src/cksum/cksum.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/cksum/cksum.rs b/src/cksum/cksum.rs index e288287f7..96f5b68ae 100644 --- a/src/cksum/cksum.rs +++ b/src/cksum/cksum.rs @@ -1,5 +1,5 @@ #![crate_name = "cksum"] -#![feature(collections, core, old_io, old_path, rustc_private)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -12,8 +12,9 @@ extern crate getopts; -use std::old_io::{EndOfFile, File, IoError, IoResult, print}; -use std::old_io::stdio::stdin_raw; +use std::io::{self, stdin, Read, Write, BufReader}; +use std::path::Path; +use std::fs::File; use std::mem; use crc_table::CRC_TABLE; @@ -43,20 +44,18 @@ fn crc_final(mut crc: u32, mut length: usize) -> u32 { } #[inline] -fn cksum(fname: &str) -> IoResult<(u32, usize)> { +fn cksum(fname: &str) -> io::Result<(u32, usize)> { let mut crc = 0u32; let mut size = 0usize; - let mut stdin_buf; - let mut file_buf; - let rd = match fname { + let file; + let mut rd : Box = match fname { "-" => { - stdin_buf = stdin_raw(); - &mut stdin_buf as &mut Reader + Box::new(stdin()) } _ => { - file_buf = try!(File::open(&Path::new(fname))); - &mut file_buf as &mut Reader + file = try!(File::open(&Path::new(fname))); + Box::new(BufReader::new(file)) } }; @@ -64,12 +63,14 @@ fn cksum(fname: &str) -> IoResult<(u32, usize)> { loop { match rd.read(&mut bytes) { Ok(num_bytes) => { + if num_bytes == 0 { + return Ok((crc_final(crc, size), size)); + } for &b in bytes[..num_bytes].iter() { crc = crc_update(crc, b); } size += num_bytes; } - Err(IoError { kind: EndOfFile, .. }) => return Ok((crc_final(crc, size), size)), Err(err) => return Err(err) } } @@ -81,7 +82,7 @@ pub fn uumain(args: Vec) -> i32 { getopts::optflag("V", "version", "output version information and exit"), ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(err) => panic!("{}", err), }; @@ -92,7 +93,7 @@ pub fn uumain(args: Vec) -> i32 { println!("Usage:"); println!(" {} [OPTIONS] [FILE]...", NAME); println!(""); - print(getopts::usage("Print CRC and size for each file.", opts.as_slice()).as_slice()); + println!("{}", getopts::usage("Print CRC and size for each file.", opts.as_ref())); return 0; } @@ -116,7 +117,7 @@ pub fn uumain(args: Vec) -> i32 { let mut exit_code = 0; for fname in files.iter() { - match cksum(fname.as_slice()) { + match cksum(fname.as_ref()) { Ok((crc, size)) => println!("{} {} {}", crc, size, fname), Err(err) => { show_error!("'{}' {}", fname, err); From 7565c27c00a27d006cdc87d710586117b6ad0b12 Mon Sep 17 00:00:00 2001 From: kwantam Date: Fri, 1 May 2015 18:36:15 -0400 Subject: [PATCH 10/11] fixed `sleep` --- src/common/time.rs | 10 +++++----- src/sleep/sleep.rs | 47 ++++++++++++++++++++++------------------------ 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/common/time.rs b/src/common/time.rs index 73a7da0f7..608601fe1 100644 --- a/src/common/time.rs +++ b/src/common/time.rs @@ -13,11 +13,11 @@ pub fn from_str(string: &str) -> Result { return Err("empty string".to_string()) } let slice = &string[..len - 1]; - let (numstr, times) = match string.char_at(len - 1) { - 's' | 'S' => (slice, 1usize), - 'm' | 'M' => (slice, 60usize), - 'h' | 'H' => (slice, 60usize * 60), - 'd' | 'D' => (slice, 60usize * 60 * 24), + let (numstr, times) = match string.chars().next_back().unwrap() { + 's' | 'S' => (slice, 1), + 'm' | 'M' => (slice, 60), + 'h' | 'H' => (slice, 60 * 60), + 'd' | 'D' => (slice, 60 * 60 * 24), val => { if !val.is_alphabetic() { (string, 1) diff --git a/src/sleep/sleep.rs b/src/sleep/sleep.rs index 886981bfe..5afc30951 100644 --- a/src/sleep/sleep.rs +++ b/src/sleep/sleep.rs @@ -1,5 +1,5 @@ #![crate_name = "sleep"] -#![feature(collections, core, old_io, rustc_private, std_misc)] +#![feature(rustc_private)] /* * This file is part of the uutils coreutils package. @@ -13,9 +13,9 @@ extern crate getopts; extern crate libc; -use std::f64; -use std::old_io::{print, timer}; -use std::time::duration::{self, Duration}; +use std::io::Write; +use std::thread::sleep_ms; +use std::u32::MAX as U32_MAX; #[path = "../common/util.rs"] #[macro_use] @@ -27,13 +27,11 @@ mod time; static NAME: &'static str = "sleep"; pub fn uumain(args: Vec) -> i32 { - let program = args[0].clone(); - let opts = [ getopts::optflag("h", "help", "display this help and exit"), getopts::optflag("V", "version", "output version information and exit") ]; - let matches = match getopts::getopts(args.tail(), &opts) { + let matches = match getopts::getopts(&args[1..], &opts) { Ok(m) => m, Err(f) => { show_error!("{}", f); @@ -45,20 +43,20 @@ pub fn uumain(args: Vec) -> i32 { println!("sleep 1.0.0"); println!(""); println!("Usage:"); - println!(" {0} NUMBER[SUFFIX]", program); + println!(" {0} NUMBER[SUFFIX]", &args[0][..]); println!("or"); - println!(" {0} OPTION", program); + println!(" {0} OPTION", &args[0][..]); println!(""); - print(getopts::usage("Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), + println!("{}", getopts::usage("Pause for NUMBER seconds. SUFFIX may be 's' for seconds (the default), 'm' for minutes, 'h' for hours or 'd' for days. Unlike most implementations that require NUMBER be an integer, here NUMBER may be an arbitrary floating point number. Given two or more arguments, pause for the amount of time -specified by the sum of their values.", &opts).as_slice()); +specified by the sum of their values.", &opts)); } else if matches.opt_present("version") { println!("sleep 1.0.0"); } else if matches.free.is_empty() { show_error!("missing an argument"); - show_error!("for help, try '{0} --help'", program); + show_error!("for help, try '{0} --help'", &args[0][..]); return 1; } else { sleep(matches.free); @@ -68,19 +66,18 @@ specified by the sum of their values.", &opts).as_slice()); } fn sleep(args: Vec) { - let sleep_time = args.iter().fold(0.0, |result, arg| { - let num = match time::from_str(arg.as_slice()) { - Ok(m) => m, - Err(f) => { - crash!(1, "{}", f) - } - }; - result + num - }); - let sleep_dur = if sleep_time == f64::INFINITY { - duration::MAX + let sleep_time = args.iter().fold(0.0, |result, arg| + match time::from_str(&arg[..]) { + Ok(m) => m + result, + Err(f) => crash!(1, "{}", f), + }); + + let sleep_dur = if sleep_time > (U32_MAX as f64) { + U32_MAX } else { - Duration::seconds(sleep_time as i64) + (1000.0 * sleep_time) as u32 }; - timer::sleep(sleep_dur); + sleep_ms(sleep_dur); } + + From ff24d48e73ec316182eaf032f8bef08fa36766dc Mon Sep 17 00:00:00 2001 From: kwantam Date: Fri, 8 May 2015 00:06:17 -0400 Subject: [PATCH 11/11] modify `factor` impl to eliminate overflow issue This change does the following: 1. Updates the arithmetic functions in `src/factor/numeric.rs` to correctly handle all cases up to 2^64. When numbers are larger than 2^63, we fall back to slightly slower routines that check for and handle overflow. 2. Since the arithmetic functions will now not overflow, we no longer need the safety net trial division implementation. We now always use Pollard's rho after eliminating small (<=13 bit) primes. 3. Slight tweak in `src/factor/gen_table.rs` to generate the first 1027 primes, which means we test every prime of 13 or fewer bits before going into Pollard's rho. Includes corresponding update in `src/factor/prime_table.rs` and the Makefile to reflect this. 4. Add a new test that generates random numbers with exclusively large (14 to 50 bit) prime factors. This exercises the possible overflow paths. 5. Add another new test that checks the `is_prime()` function against a few dozen 64-bit primes. Again this is to exercise possible overflow paths. --- Makefile | 2 +- src/factor/factor.rs | 41 +--- src/factor/gen_table.rs | 8 +- src/factor/numeric.rs | 82 +++++-- src/factor/prime_table.rs | 17 +- test/factor.rs | 455 +++++++++++++++++++++++++++++++++++++- 6 files changed, 550 insertions(+), 55 deletions(-) diff --git a/Makefile b/Makefile index 6218c782f..174ae078e 100644 --- a/Makefile +++ b/Makefile @@ -307,7 +307,7 @@ $(SRCDIR)/cksum/crc_table.rs: $(SRCDIR)/cksum/gen_table.rs cd $(SRCDIR)/cksum && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table && $(RM) gen_table $(SRCDIR)/factor/prime_table.rs: $(SRCDIR)/factor/gen_table.rs - cd $(SRCDIR)/factor && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table 1000 > $@ && $(RM) gen_table + cd $(SRCDIR)/factor && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table > $@ && $(RM) gen_table crates: echo $(EXES) diff --git a/src/factor/factor.rs b/src/factor/factor.rs index 273797bdf..64aeee8b6 100644 --- a/src/factor/factor.rs +++ b/src/factor/factor.rs @@ -19,7 +19,7 @@ extern crate libc; extern crate rand; use numeric::*; -use prime_table::{P_INVS_U64, NEXT_PRIME}; +use prime_table::P_INVS_U64; use std::cmp::{max, min}; use std::io::{stdin, BufRead, BufReader, Write}; use std::num::Wrapping; @@ -36,33 +36,12 @@ mod prime_table; static VERSION: &'static str = "1.0.0"; static NAME: &'static str = "factor"; -fn trial_division_slow(mut num: u64, factors: &mut Vec) { - // assumption: this number has already been run through - // trial_division, which checks primes from the table. - // The first candidate we need to check is NEXT_PRIME. - let mut i = NEXT_PRIME; - while i * i <= num { - while num % i == 0 { - num /= i; - factors.push(i); - if is_prime(num) { - factors.push(num); - return; - } - if num < 1 << 63 { - // once we're small enough, switch to Pollard's rho - return rho_pollard_factor(num, factors); - } - } - i += 2; - } - if num > 1 { - factors.push(num); - } -} - fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 { - (multiply(a, multiply(x, x, num), num) + b) % num + if num < 1 << 63 { + (sm_mul(a, sm_mul(x, x, num), num) + b) % num + } else { + big_add(big_mul(a, big_mul(x, x, num), num), b, num) + } } fn gcd(mut a: u64, mut b: u64) -> u64 { @@ -148,13 +127,13 @@ fn table_division(mut num: u64, factors: &mut Vec) { // do we still have more factoring to do? // Decide whether to use Pollard Rho or slow divisibility based on // number's size: - if num >= 1 << 63 { + //if num >= 1 << 63 { // number is too big to use rho pollard without overflowing - trial_division_slow(num, factors); - } else if num > 1 { + //trial_division_slow(num, factors); + //} else if num > 1 { // number is still greater than 1, but not so big that we have to worry rho_pollard_factor(num, factors); - } + //} } fn print_factors(num: u64) { diff --git a/src/factor/gen_table.rs b/src/factor/gen_table.rs index fefa87b0b..02826d0af 100644 --- a/src/factor/gen_table.rs +++ b/src/factor/gen_table.rs @@ -8,7 +8,9 @@ */ //! Generate a table of the multiplicative inverses of p_i mod 2^64 -//! for the first 10000 odd primes. +//! for the first 1027 odd primes (all 13 bit and smaller primes). +//! You can supply a commandline argument to override the default +//! value of 1027 for the number of entries in the table. //! //! 2 has no multiplicative inverse mode 2^64 because 2 | 2^64, //! and in any case divisibility by two is trivial by checking the LSB. @@ -65,7 +67,7 @@ fn inv_mod_u64(a: u64) -> Option { #[cfg_attr(test, allow(dead_code))] fn main() { // By default, we print the multiplicative inverses mod 2^64 of the first 1k primes - let n = args().skip(1).next().unwrap_or("1000".to_string()).parse::().ok().unwrap_or(1000); + let n = args().skip(1).next().unwrap_or("1027".to_string()).parse::().ok().unwrap_or(1027); print!("{}", PREAMBLE); let mut cols = 3; @@ -91,7 +93,7 @@ fn main() { x = next; } - print!("\n];\n\npub const NEXT_PRIME: u64 = {};\n", x); + print!("\n];\n\n#[allow(dead_code)]\npub const NEXT_PRIME: u64 = {};\n", x); } #[test] diff --git a/src/factor/numeric.rs b/src/factor/numeric.rs index 0d3888f65..16a0652a1 100644 --- a/src/factor/numeric.rs +++ b/src/factor/numeric.rs @@ -2,16 +2,36 @@ * This file is part of the uutils coreutils package. * * (c) Wiktor Kuropatwa +* (c) kwantam +* 20150507 added big_ routines to prevent overflow when num > 2^63 * * For the full copyright and license information, please view the LICENSE file * that was distributed with this source code. */ +use std::u64::MAX as MAX_U64; +use std::num::Wrapping; + +pub fn big_add(a: u64, b: u64, m: u64) -> u64 { + let Wrapping(msb_mod_m) = Wrapping(MAX_U64) - Wrapping(m) + Wrapping(1); + let msb_mod_m = msb_mod_m % m; + + let Wrapping(res) = Wrapping(a) + Wrapping(b); + let res = if b <= MAX_U64 - a { + res + } else { + (res + msb_mod_m) % m + }; + + res +} + // computes (a + b) % m using the russian peasant algorithm -pub fn multiply(mut a: u64, mut b: u64, m: u64) -> u64 { +// CAUTION: Will overflow if m >= 2^63 +pub fn sm_mul(mut a: u64, mut b: u64, m: u64) -> u64 { let mut result = 0; while b > 0 { - if b & 1 > 0 { + if b & 1 != 0 { result = (result + a) % m; } a = (a << 1) % m; @@ -20,14 +40,44 @@ pub fn multiply(mut a: u64, mut b: u64, m: u64) -> u64 { result } +// computes (a + b) % m using the russian peasant algorithm +// Only necessary when m >= 2^63; otherwise, just wastes time. +pub fn big_mul(mut a: u64, mut b: u64, m: u64) -> u64 { + // precompute 2^64 mod m, since we expect to wrap + let Wrapping(msb_mod_m) = Wrapping(MAX_U64) - Wrapping(m) + Wrapping(1); + let msb_mod_m = msb_mod_m % m; + + let mut result = 0; + while b > 0 { + if b & 1 != 0 { + let Wrapping(next_res) = Wrapping(result) + Wrapping(a); + let next_res = next_res % m; + result = if result <= MAX_U64 - a { + next_res + } else { + (next_res + msb_mod_m) % m + }; + } + let Wrapping(next_a) = Wrapping(a) << 1; + let next_a = next_a % m; + a = if a < 1 << 63 { + next_a + } else { + (next_a + msb_mod_m) % m + }; + b >>= 1; + } + result +} + // computes a.pow(b) % m -fn pow(mut a: u64, mut b: u64, m: u64) -> u64 { +fn pow(mut a: u64, mut b: u64, m: u64, mul: fn(u64, u64, u64) -> u64) -> u64 { let mut result = 1; while b > 0 { - if b & 1 > 0 { - result = multiply(result, a, m); + if b & 1 != 0 { + result = mul(result, a, m); } - a = multiply(a, a, m); + a = mul(a, a, m); b >>= 1; } result @@ -37,10 +87,17 @@ fn witness(mut a: u64, exponent: u64, m: u64) -> bool { if a == 0 { return false; } - if pow(a, m-1, m) != 1 { + + let mul = if m < 1 << 63 { + sm_mul as fn(u64, u64, u64) -> u64 + } else { + big_mul as fn(u64, u64, u64) -> u64 + }; + + if pow(a, m-1, m, mul) != 1 { return true; } - a = pow(a, exponent, m); + a = pow(a, exponent, m, mul); if a == 1 { return false; } @@ -51,7 +108,7 @@ fn witness(mut a: u64, exponent: u64, m: u64) -> bool { if a == m-1 { return false; } - a = multiply(a, a, m); + a = mul(a, a, m); } } @@ -71,10 +128,5 @@ pub fn is_prime(num: u64) -> bool { // These witnesses detect all composites up to at least 2^64. // Discovered by Jim Sinclair, according to http://miller-rabin.appspot.com let witnesses = [2, 325, 9375, 28178, 450775, 9780504, 1795265022]; - for wit in witnesses.iter() { - if witness(*wit % num, exponent, num) { - return false; - } - } - true + ! witnesses.iter().any(|&wit| witness(wit % num, exponent, num)) } diff --git a/src/factor/prime_table.rs b/src/factor/prime_table.rs index 968f7e9fe..43f01eb4b 100644 --- a/src/factor/prime_table.rs +++ b/src/factor/prime_table.rs @@ -512,6 +512,21 @@ pub const P_INVS_U64: &'static [(u64, u64, u64)] = &[ (7879, 15749618908978823927, 2341254483273201), (7883, 13069271299209418467, 2340066481505715), (7901, 7641588830939294069, 2334735359284843), (7907, 12420698804657854155, 2332963712369995), (7919, 12818844884155027471, 2329428472497733), (7927, 7937661667140567751, 2327077592242910), + (7933, 17988656517612138069, 2325317543641693), (7937, 12066964247284867329, 2324145656256715), + (7949, 10178314191381317573, 2320637070538376), (7951, 5681810619609444335, 2320053335896057), + (7963, 6180574304741565203, 2316557085735219), (7993, 7117447607071219465, 2307862388803897), + (8009, 15818733711853814521, 2303251850881452), (8011, 6594866437037093475, 2302676828574404), + (8017, 12876135691215997361, 2300953483062186), (8039, 16092426444697734231, 2294656558491050), + (8053, 7540876877021214941, 2290667338098789), (8059, 6493784953110063027, 2288961915089905), + (8069, 14763796409470353741, 2286125179540160), (8081, 12739918163021037937, 2282730364275405), + (8087, 10456272391972868135, 2281036734723575), (8089, 11422888004105716905, 2280472749871374), + (8093, 18241602968231501493, 2279345616422779), (8101, 4561020661602299949, 2277094688767997), + (8111, 16802434375116035919, 2274287273296702), (8117, 16051417197561976477, 2272606144352538), + (8123, 11545395404498259315, 2270927498917832), (8147, 11443457045357563995, 2264237642532165), + (8161, 12755174219819017249, 2260353397097114), (8167, 10672323466178233303, 2258692797074758), + (8171, 17536936478347301059, 2257587085266130), (8179, 16031233265182478651, 2255378906187743), + (8191, 18442239924259250175, 2252074725150720), ]; -pub const NEXT_PRIME: u64 = 7933; +#[allow(dead_code)] +pub const NEXT_PRIME: u64 = 8209; diff --git a/test/factor.rs b/test/factor.rs index 69d0860fb..872ea0d27 100644 --- a/test/factor.rs +++ b/test/factor.rs @@ -11,6 +11,7 @@ extern crate libc; extern crate rand; use rand::{weak_rng, Rng}; +use rand::distributions::{IndependentSample, Range}; use sieve::Sieve; use std::io::Write; use std::process::{Command, Stdio}; @@ -26,7 +27,6 @@ const PROGNAME: &'static str = "./factor"; #[test] fn test_random() { - let mut primes = Sieve::new().take(NUM_PRIMES - 1).collect::>(); primes.push(2); let primes = primes; @@ -68,12 +68,101 @@ fn test_random() { instring.push_str(&(format!("{} ", product))[..]); outstring.push_str(&(format!("{}:", product))[..]); - for factor in factors.iter() { + for factor in factors { outstring.push_str(&(format!(" {}", factor))[..]); } outstring.push_str("\n"); } + run(instring.as_bytes(), outstring.as_bytes()); +} + +#[test] +fn test_random_big() { + let mut rng = weak_rng(); + let bitrange_1 = Range::new(14usize, 51); + let mut rand_64 = move || { + // first, choose a random number of bits for the first factor + let f_bit_1 = bitrange_1.ind_sample(&mut rng); + // how many more bits do we need? + let rem = 64 - f_bit_1; + + // we will have a number of additional factors equal to nfacts + 1 + // where nfacts is in [0, floor(rem/14) ) NOTE half-open interval + // Each prime factor is at least 14 bits, hence floor(rem/14) + let nfacts = Range::new(0usize, rem / 14).ind_sample(&mut rng); + // we have to distribute extrabits among the (nfacts + 1) values + let extrabits = rem - (nfacts + 1) * 14; + // (remember, a Range is a half-open interval) + let extrarange = Range::new(0usize, extrabits + 1); + + // to generate an even split of this range, generate n-1 random elements + // in the range, add the desired total value to the end, sort this list, + // and then compute the sequential differences. + let mut f_bits = Vec::new(); + for _ in 0..nfacts { + f_bits.push(extrarange.ind_sample(&mut rng)); + } + f_bits.push(extrabits); + f_bits.sort(); + + // compute sequential differences here. We leave off the +14 bits + // so we can just index PRIMES_BY_BITS + let mut f_bits = f_bits.iter().scan(0, |st,&x| { + let ret = x - *st; // + 14 would give actual number of bits + *st = x; + Some(ret) + }).collect::>(); + // finally, add f_bit_1 in there + f_bits.push(f_bit_1 - 14); // index of f_bit_1 in PRIMES_BY_BITS + let f_bits = f_bits; + + let mut nbits = 0; + let mut product = 1u64; + let mut factors = Vec::new(); + for bit in f_bits { + assert!(bit < 37); + nbits += 14 + bit; + let elm = Range::new(0, PRIMES_BY_BITS[bit].len()).ind_sample(&mut rng); + let factor = PRIMES_BY_BITS[bit][elm]; + factors.push(factor); + product *= factor; + } + assert_eq!(nbits, 64); + + factors.sort(); + (product, factors) + }; + + let mut instring = String::new(); + let mut outstring = String::new(); + for _ in 0..NUM_TESTS { + let (product, factors) = rand_64(); + instring.push_str(&(format!("{} ", product))[..]); + + outstring.push_str(&(format!("{}:", product))[..]); + for factor in factors { + outstring.push_str(&(format!(" {}", factor))[..]); + } + outstring.push_str("\n"); + } + + run(instring.as_bytes(), outstring.as_bytes()); +} + +#[test] +fn test_big_primes() { + let mut instring = String::new(); + let mut outstring = String::new(); + for prime in PRIMES64 { + instring.push_str(&(format!("{} ", prime))[..]); + outstring.push_str(&(format!("{0}: {0}\n", prime))[..]); + } + + run(instring.as_bytes(), outstring.as_bytes()); +} + +fn run(instring: &[u8], outstring: &[u8]) { // now run factor let mut process = Command::new(PROGNAME) .stdin(Stdio::piped()) @@ -82,8 +171,366 @@ fn test_random() { .unwrap_or_else(|e| panic!("{}", e)); process.stdin.take().unwrap_or_else(|| panic!("Could not take child process stdin")) - .write_all(instring.as_bytes()).unwrap_or_else(|e| panic!("{}", e)); + .write_all(instring).unwrap_or_else(|e| panic!("{}", e)); let output = process.wait_with_output().unwrap_or_else(|e| panic!("{}", e)); - assert_eq!(&output.stdout[..], outstring.as_bytes()); + assert_eq!(&output.stdout[..], outstring); } + +const PRIMES_BY_BITS: &'static [&'static [u64]] = &[PRIMES14, PRIMES15, PRIMES16, PRIMES17, + PRIMES18, PRIMES19, PRIMES20, PRIMES21, PRIMES22, PRIMES23, PRIMES24, PRIMES25, PRIMES26, + PRIMES27, PRIMES28, PRIMES29, PRIMES30, PRIMES31, PRIMES32, PRIMES33, PRIMES34, PRIMES35, + PRIMES36, PRIMES37, PRIMES38, PRIMES39, PRIMES40, PRIMES41, PRIMES42, PRIMES43, PRIMES44, + PRIMES45, PRIMES46, PRIMES47, PRIMES48, PRIMES49, PRIMES50, +]; + +const PRIMES64: &'static [u64] = &[18446744073709551557, 18446744073709551533, + 18446744073709551521, 18446744073709551437, 18446744073709551427, 18446744073709551359, + 18446744073709551337, 18446744073709551293, 18446744073709551263, 18446744073709551253, + 18446744073709551191, 18446744073709551163, 18446744073709551113, 18446744073709550873, + 18446744073709550791, 18446744073709550773, 18446744073709550771, 18446744073709550719, + 18446744073709550717, 18446744073709550681, 18446744073709550671, 18446744073709550593, + 18446744073709550591, 18446744073709550539, 18446744073709550537, 18446744073709550381, + 18446744073709550341, 18446744073709550293, 18446744073709550237, 18446744073709550147, + 18446744073709550141, 18446744073709550129, 18446744073709550111, 18446744073709550099, + 18446744073709550047, 18446744073709550033, 18446744073709550009, 18446744073709549951, + 18446744073709549861, 18446744073709549817, 18446744073709549811, 18446744073709549777, + 18446744073709549757, 18446744073709549733, 18446744073709549667, 18446744073709549621, + 18446744073709549613, 18446744073709549583, 18446744073709549571, +]; + +const PRIMES14: &'static [u64] = &[16381, 16369, 16363, 16361, 16349, 16339, 16333, 16319, + 16301, 16273, 16267, 16253, 16249, 16231, 16229, 16223, 16217, 16193, 16189, 16187, 16183, + 16141, 16139, 16127, 16111, 16103, 16097, 16091, 16087, 16073, 16069, 16067, 16063, 16061, + 16057, 16033, 16007, 16001, 15991, 15973, 15971, 15959, 15937, 15923, 15919, 15913, 15907, + 15901, 15889, 15887, 15881, 15877, 15859, 15823, 15817, 15809, 15803, 15797, 15791, 15787, + 15773, 15767, 15761, 15749, 15739, 15737, 15733, 15731, 15727, 15683, 15679, 15671, 15667, + 15661, 15649, 15647, 15643, 15641, 15629, 15619, 15607, 15601, 15583, 15581, 15569, 15559, + 15551, 15541, 15527, 15511, 15497, 15493, 15473, 15467, 15461, 15451, 15443, 15439, 15427, + 15413, 15401, 15391, 15383, 15377, 15373, +]; + +const PRIMES15: &'static [u64] = &[32749, 32719, 32717, 32713, 32707, 32693, 32687, 32653, + 32647, 32633, 32621, 32611, 32609, 32603, 32587, 32579, 32573, 32569, 32563, 32561, 32537, + 32533, 32531, 32507, 32503, 32497, 32491, 32479, 32467, 32443, 32441, 32429, 32423, 32413, + 32411, 32401, 32381, 32377, 32371, 32369, 32363, 32359, 32353, 32341, 32327, 32323, 32321, + 32309, 32303, 32299, 32297, 32261, 32257, 32251, 32237, 32233, 32213, 32203, 32191, 32189, + 32183, 32173, 32159, 32143, 32141, 32119, 32117, 32099, 32089, 32083, 32077, 32069, 32063, + 32059, 32057, 32051, 32029, 32027, 32009, 32003, 31991, 31981, 31973, 31963, 31957, 31907, + 31891, 31883, 31873, 31859, 31849, 31847, 31817, 31799, 31793, 31771, 31769, 31751, +]; + +const PRIMES16: &'static [u64] = &[65521, 65519, 65497, 65479, 65449, 65447, 65437, 65423, + 65419, 65413, 65407, 65393, 65381, 65371, 65357, 65353, 65327, 65323, 65309, 65293, 65287, + 65269, 65267, 65257, 65239, 65213, 65203, 65183, 65179, 65173, 65171, 65167, 65147, 65141, + 65129, 65123, 65119, 65111, 65101, 65099, 65089, 65071, 65063, 65053, 65033, 65029, 65027, + 65011, 65003, 64997, 64969, 64951, 64937, 64927, 64921, 64919, 64901, 64891, 64879, 64877, + 64871, 64853, 64849, 64817, 64811, 64793, 64783, 64781, 64763, 64747, 64717, 64709, 64693, + 64679, 64667, 64663, 64661, 64633, 64627, 64621, 64613, 64609, 64601, 64591, 64579, 64577, + 64567, 64553, +]; + +const PRIMES17: &'static [u64] = &[131071, 131063, 131059, 131041, 131023, 131011, 131009, + 130987, 130981, 130973, 130969, 130957, 130927, 130873, 130859, 130843, 130841, 130829, + 130817, 130811, 130807, 130787, 130783, 130769, 130729, 130699, 130693, 130687, 130681, + 130657, 130651, 130649, 130643, 130639, 130633, 130631, 130621, 130619, 130589, 130579, + 130553, 130547, 130531, 130523, 130517, 130513, 130489, 130483, 130477, 130469, 130457, + 130447, 130439, 130423, 130411, 130409, 130399, 130379, 130369, 130367, 130363, 130349, + 130343, 130337, 130307, 130303, 130279, 130267, 130261, 130259, 130253, 130241, 130223, + 130211, 130201, 130199, 130183, 130171, 130147, 130127, 130121, 130099, 130087, 130079, + 130073, 130069, 130057, 130051, +]; + +const PRIMES18: &'static [u64] = &[262139, 262133, 262127, 262121, 262111, 262109, 262103, + 262079, 262069, 262051, 262049, 262027, 262007, 261983, 261977, 261973, 261971, 261959, + 261917, 261887, 261881, 261847, 261823, 261799, 261791, 261787, 261773, 261761, 261757, + 261739, 261721, 261713, 261707, 261697, 261673, 261643, 261641, 261637, 261631, 261619, + 261601, 261593, 261587, 261581, 261577, 261563, 261557, 261529, 261523, 261509, 261467, + 261463, 261451, 261439, 261433, 261431, 261427, 261407, 261389, 261379, 261353, 261347, + 261337, 261329, 261323, 261301, 261281, 261271, 261251, 261241, 261229, 261223, 261169, + 261167, 261127, +]; + +const PRIMES19: &'static [u64] = &[524287, 524269, 524261, 524257, 524243, 524231, 524221, + 524219, 524203, 524201, 524197, 524189, 524171, 524149, 524123, 524119, 524113, 524099, + 524087, 524081, 524071, 524063, 524057, 524053, 524047, 523997, 523987, 523969, 523949, + 523937, 523927, 523907, 523903, 523877, 523867, 523847, 523829, 523801, 523793, 523777, + 523771, 523763, 523759, 523741, 523729, 523717, 523681, 523673, 523669, 523667, 523657, + 523639, 523637, 523631, 523603, 523597, 523577, 523573, 523571, 523553, 523543, 523541, + 523519, 523511, 523493, 523489, 523487, 523463, 523459, 523433, 523427, 523417, 523403, + 523387, 523357, 523351, 523349, 523333, 523307, 523297, +]; + +const PRIMES20: &'static [u64] = &[1048573, 1048571, 1048559, 1048549, 1048517, 1048507, + 1048447, 1048433, 1048423, 1048391, 1048387, 1048367, 1048361, 1048357, 1048343, 1048309, + 1048291, 1048273, 1048261, 1048219, 1048217, 1048213, 1048193, 1048189, 1048139, 1048129, + 1048127, 1048123, 1048063, 1048051, 1048049, 1048043, 1048027, 1048013, 1048009, 1048007, + 1047997, 1047989, 1047979, 1047971, 1047961, 1047941, 1047929, 1047923, 1047887, 1047883, + 1047881, 1047859, 1047841, 1047833, 1047821, 1047779, 1047773, 1047763, 1047751, 1047737, + 1047721, 1047713, 1047703, 1047701, 1047691, 1047689, 1047671, 1047667, 1047653, 1047649, + 1047647, 1047589, 1047587, 1047559, +]; + +const PRIMES21: &'static [u64] = &[2097143, 2097133, 2097131, 2097097, 2097091, 2097083, + 2097047, 2097041, 2097031, 2097023, 2097013, 2096993, 2096987, 2096971, 2096959, 2096957, + 2096947, 2096923, 2096911, 2096909, 2096893, 2096881, 2096873, 2096867, 2096851, 2096837, + 2096807, 2096791, 2096789, 2096777, 2096761, 2096741, 2096737, 2096713, 2096693, 2096687, + 2096681, 2096639, 2096629, 2096621, 2096599, 2096597, 2096569, 2096539, 2096533, 2096483, + 2096449, 2096431, 2096429, 2096411, 2096407, 2096401, 2096399, 2096377, 2096357, 2096291, + 2096273, 2096261, 2096233, 2096231, 2096221, 2096209, 2096191, 2096183, 2096147, +]; + +const PRIMES22: &'static [u64] = &[4194301, 4194287, 4194277, 4194271, 4194247, 4194217, + 4194199, 4194191, 4194187, 4194181, 4194173, 4194167, 4194143, 4194137, 4194131, 4194107, + 4194103, 4194023, 4194011, 4194007, 4193977, 4193971, 4193963, 4193957, 4193939, 4193929, + 4193909, 4193869, 4193807, 4193803, 4193801, 4193789, 4193759, 4193753, 4193743, 4193701, + 4193663, 4193633, 4193573, 4193569, 4193551, 4193549, 4193531, 4193513, 4193507, 4193459, + 4193447, 4193443, 4193417, 4193411, 4193393, 4193389, 4193381, 4193377, 4193369, 4193359, + 4193353, 4193327, 4193309, 4193303, 4193297, +]; + +const PRIMES23: &'static [u64] = &[8388593, 8388587, 8388581, 8388571, 8388547, 8388539, + 8388473, 8388461, 8388451, 8388449, 8388439, 8388427, 8388421, 8388409, 8388377, 8388371, + 8388319, 8388301, 8388287, 8388283, 8388277, 8388239, 8388209, 8388187, 8388113, 8388109, + 8388091, 8388071, 8388059, 8388019, 8388013, 8387999, 8387993, 8387959, 8387957, 8387947, + 8387933, 8387921, 8387917, 8387891, 8387879, 8387867, 8387861, 8387857, 8387839, 8387831, + 8387809, 8387807, 8387741, 8387737, 8387723, 8387707, 8387671, 8387611, 8387609, 8387591, +]; + +const PRIMES24: &'static [u64] = &[16777213, 16777199, 16777183, 16777153, 16777141, 16777139, + 16777127, 16777121, 16777099, 16777049, 16777027, 16776989, 16776973, 16776971, 16776967, + 16776961, 16776941, 16776937, 16776931, 16776919, 16776901, 16776899, 16776869, 16776857, + 16776839, 16776833, 16776817, 16776763, 16776731, 16776719, 16776713, 16776691, 16776689, + 16776679, 16776659, 16776631, 16776623, 16776619, 16776607, 16776593, 16776581, 16776547, + 16776521, 16776491, 16776481, 16776469, 16776451, 16776401, 16776391, 16776379, 16776371, + 16776367, 16776343, 16776337, 16776317, 16776313, 16776289, 16776217, 16776211, +]; + +const PRIMES25: &'static [u64] = &[33554393, 33554383, 33554371, 33554347, 33554341, 33554317, + 33554291, 33554273, 33554267, 33554249, 33554239, 33554221, 33554201, 33554167, 33554159, + 33554137, 33554123, 33554093, 33554083, 33554077, 33554051, 33554021, 33554011, 33554009, + 33553999, 33553991, 33553969, 33553967, 33553909, 33553901, 33553879, 33553837, 33553799, + 33553787, 33553771, 33553769, 33553759, 33553747, 33553739, 33553727, 33553697, 33553693, + 33553679, 33553661, 33553657, 33553651, 33553649, 33553633, 33553613, 33553607, 33553577, + 33553549, 33553547, 33553537, 33553519, 33553517, 33553511, 33553489, 33553463, 33553451, + 33553417, +]; + +const PRIMES26: &'static [u64] = &[67108859, 67108837, 67108819, 67108777, 67108763, + 67108757, 67108753, 67108747, 67108739, 67108729, 67108721, 67108709, 67108693, 67108669, + 67108667, 67108661, 67108649, 67108633, 67108597, 67108579, 67108529, 67108511, 67108507, + 67108493, 67108471, 67108463, 67108453, 67108439, 67108387, 67108373, 67108369, 67108351, + 67108331, 67108313, 67108303, 67108289, 67108271, 67108219, 67108207, 67108201, 67108199, + 67108187, 67108183, 67108177, 67108127, 67108109, 67108081, 67108049, 67108039, 67108037, + 67108033, 67108009, 67108007, 67108003, 67107983, 67107977, 67107967, 67107941, 67107919, + 67107913, 67107883, 67107881, 67107871, 67107863, +]; + +const PRIMES27: &'static [u64] = &[134217689, 134217649, 134217617, 134217613, 134217593, + 134217541, 134217529, 134217509, 134217497, 134217493, 134217487, 134217467, 134217439, + 134217437, 134217409, 134217403, 134217401, 134217367, 134217361, 134217353, 134217323, + 134217301, 134217277, 134217257, 134217247, 134217221, 134217199, 134217173, 134217163, + 134217157, 134217131, 134217103, 134217089, 134217079, 134217049, 134217047, 134217043, + 134217001, 134216987, 134216947, 134216939, 134216933, 134216911, 134216899, 134216881, + 134216869, 134216867, 134216861, 134216837, 134216827, 134216807, 134216801, 134216791, + 134216783, 134216777, 134216759, 134216737, 134216729, +]; + +const PRIMES28: &'static [u64] = &[268435399, 268435367, 268435361, 268435337, 268435331, + 268435313, 268435291, 268435273, 268435243, 268435183, 268435171, 268435157, 268435147, + 268435133, 268435129, 268435121, 268435109, 268435091, 268435067, 268435043, 268435039, + 268435033, 268435019, 268435009, 268435007, 268434997, 268434979, 268434977, 268434961, + 268434949, 268434941, 268434937, 268434857, 268434841, 268434827, 268434821, 268434787, + 268434781, 268434779, 268434773, 268434731, 268434721, 268434713, 268434707, 268434703, + 268434697, 268434659, 268434623, 268434619, 268434581, 268434577, 268434563, 268434557, + 268434547, 268434511, 268434499, 268434479, 268434461, +]; + +const PRIMES29: &'static [u64] = &[536870909, 536870879, 536870869, 536870849, 536870839, + 536870837, 536870819, 536870813, 536870791, 536870779, 536870767, 536870743, 536870729, + 536870723, 536870717, 536870701, 536870683, 536870657, 536870641, 536870627, 536870611, + 536870603, 536870599, 536870573, 536870569, 536870563, 536870561, 536870513, 536870501, + 536870497, 536870473, 536870401, 536870363, 536870317, 536870303, 536870297, 536870273, + 536870267, 536870239, 536870233, 536870219, 536870171, 536870167, 536870153, 536870123, + 536870063, 536870057, 536870041, 536870027, 536869999, 536869951, 536869943, 536869937, + 536869919, 536869901, 536869891, +]; + +const PRIMES30: &'static [u64] = &[1073741789, 1073741783, 1073741741, 1073741723, 1073741719, + 1073741717, 1073741689, 1073741671, 1073741663, 1073741651, 1073741621, 1073741567, 1073741561, + 1073741527, 1073741503, 1073741477, 1073741467, 1073741441, 1073741419, 1073741399, 1073741387, + 1073741381, 1073741371, 1073741329, 1073741311, 1073741309, 1073741287, 1073741237, 1073741213, + 1073741197, 1073741189, 1073741173, 1073741101, 1073741077, 1073741047, 1073740963, 1073740951, + 1073740933, 1073740909, 1073740879, 1073740853, 1073740847, 1073740819, 1073740807, +]; + +const PRIMES31: &'static [u64] = &[2147483647, 2147483629, 2147483587, 2147483579, 2147483563, + 2147483549, 2147483543, 2147483497, 2147483489, 2147483477, 2147483423, 2147483399, 2147483353, + 2147483323, 2147483269, 2147483249, 2147483237, 2147483179, 2147483171, 2147483137, 2147483123, + 2147483077, 2147483069, 2147483059, 2147483053, 2147483033, 2147483029, 2147482951, 2147482949, + 2147482943, 2147482937, 2147482921, 2147482877, 2147482873, 2147482867, 2147482859, 2147482819, + 2147482817, 2147482811, 2147482801, 2147482763, 2147482739, 2147482697, 2147482693, 2147482681, + 2147482663, 2147482661, +]; + +const PRIMES32: &'static [u64] = &[4294967291, 4294967279, 4294967231, 4294967197, 4294967189, + 4294967161, 4294967143, 4294967111, 4294967087, 4294967029, 4294966997, 4294966981, 4294966943, + 4294966927, 4294966909, 4294966877, 4294966829, 4294966813, 4294966769, 4294966667, 4294966661, + 4294966657, 4294966651, 4294966639, 4294966619, 4294966591, 4294966583, 4294966553, 4294966477, + 4294966447, 4294966441, 4294966427, 4294966373, 4294966367, 4294966337, 4294966297, +]; + +const PRIMES33: &'static [u64] = &[8589934583, 8589934567, 8589934543, 8589934513, 8589934487, + 8589934307, 8589934291, 8589934289, 8589934271, 8589934237, 8589934211, 8589934207, 8589934201, + 8589934187, 8589934151, 8589934141, 8589934139, 8589934117, 8589934103, 8589934099, 8589934091, + 8589934069, 8589934049, 8589934027, 8589934007, 8589933973, 8589933971, 8589933967, 8589933931, + 8589933917, 8589933907, 8589933853, 8589933827, 8589933823, 8589933787, 8589933773, 8589933733, + 8589933731, 8589933721, 8589933683, 8589933647, 8589933641, 8589933637, 8589933631, 8589933629, + 8589933619, 8589933601, 8589933581, +]; + +const PRIMES34: &'static [u64] = &[17179869143, 17179869107, 17179869071, 17179869053, + 17179869041, 17179869019, 17179868999, 17179868977, 17179868957, 17179868903, 17179868899, + 17179868887, 17179868879, 17179868873, 17179868869, 17179868861, 17179868843, 17179868833, + 17179868809, 17179868807, 17179868777, 17179868759, 17179868729, 17179868711, 17179868683, + 17179868681, 17179868597, 17179868549, 17179868543, 17179868521, 17179868513, 17179868479, + 17179868443, 17179868437, 17179868429, 17179868383, 17179868369, 17179868357, 17179868353, + 17179868351, 17179868333, 17179868317, 17179868309, 17179868297, 17179868287, 17179868249, + 17179868243, 17179868183, +]; + +const PRIMES35: &'static [u64] = &[34359738337, 34359738319, 34359738307, 34359738299, + 34359738289, 34359738247, 34359738227, 34359738121, 34359738059, 34359738043, 34359738011, + 34359737917, 34359737869, 34359737849, 34359737837, 34359737821, 34359737813, 34359737791, + 34359737777, 34359737771, 34359737717, 34359737591, 34359737567, 34359737549, 34359737519, + 34359737497, 34359737479, 34359737407, 34359737393, 34359737371, +]; + +const PRIMES36: &'static [u64] = &[68719476731, 68719476719, 68719476713, 68719476671, + 68719476619, 68719476599, 68719476577, 68719476563, 68719476547, 68719476503, 68719476493, + 68719476479, 68719476433, 68719476407, 68719476391, 68719476389, 68719476377, 68719476361, + 68719476323, 68719476307, 68719476281, 68719476271, 68719476257, 68719476247, 68719476209, + 68719476197, 68719476181, 68719476169, 68719476157, 68719476149, 68719476109, 68719476053, + 68719476047, 68719476019, 68719475977, 68719475947, 68719475933, 68719475911, 68719475893, + 68719475879, 68719475837, 68719475827, 68719475809, 68719475791, 68719475779, 68719475771, + 68719475767, 68719475731, 68719475729, +]; + +const PRIMES37: &'static [u64] = &[137438953447, 137438953441, 137438953427, 137438953403, + 137438953349, 137438953331, 137438953273, 137438953271, 137438953121, 137438953097, + 137438953037, 137438953009, 137438952953, 137438952901, 137438952887, 137438952869, + 137438952853, 137438952731, 137438952683, 137438952611, 137438952529, 137438952503, + 137438952491, +]; + +const PRIMES38: &'static [u64] = &[274877906899, 274877906857, 274877906837, 274877906813, + 274877906791, 274877906759, 274877906753, 274877906717, 274877906713, 274877906687, + 274877906647, 274877906629, 274877906627, 274877906573, 274877906543, 274877906491, + 274877906477, 274877906473, 274877906431, 274877906419, 274877906341, 274877906333, + 274877906327, 274877906321, 274877906309, 274877906267, 274877906243, 274877906213, + 274877906209, 274877906203, 274877906179, 274877906167, 274877906119, 274877906063, + 274877906053, 274877906021, 274877905931, +]; + +const PRIMES39: &'static [u64] = &[549755813881, 549755813869, 549755813821, 549755813797, + 549755813753, 549755813723, 549755813669, 549755813657, 549755813647, 549755813587, + 549755813561, 549755813513, 549755813507, 549755813461, 549755813417, 549755813401, + 549755813371, 549755813359, 549755813357, 549755813351, 549755813339, 549755813317, + 549755813311, 549755813281, 549755813239, 549755813231, 549755813213, 549755813207, + 549755813197, 549755813183, 549755813161, 549755813149, 549755813147, 549755813143, + 549755813141, 549755813059, 549755813027, 549755813003, 549755812951, 549755812937, + 549755812933, 549755812889, 549755812867, +]; + +const PRIMES40: &'static [u64] = &[1099511627689, 1099511627609, 1099511627581, 1099511627573, + 1099511627563, 1099511627491, 1099511627483, 1099511627477, 1099511627387, 1099511627339, + 1099511627321, 1099511627309, 1099511627297, 1099511627293, 1099511627261, 1099511627213, + 1099511627191, 1099511627177, 1099511627173, 1099511627143, 1099511627089, 1099511626987, + 1099511626949, 1099511626937, 1099511626793, 1099511626781, 1099511626771, +]; + +const PRIMES41: &'static [u64] = &[2199023255531, 2199023255521, 2199023255497, 2199023255489, + 2199023255479, 2199023255477, 2199023255461, 2199023255441, 2199023255419, 2199023255413, + 2199023255357, 2199023255327, 2199023255291, 2199023255279, 2199023255267, 2199023255243, + 2199023255203, 2199023255171, 2199023255137, 2199023255101, 2199023255087, 2199023255081, + 2199023255069, 2199023255027, 2199023255021, 2199023254979, 2199023254933, 2199023254913, + 2199023254907, 2199023254903, 2199023254843, 2199023254787, 2199023254699, 2199023254693, + 2199023254657, 2199023254567, +]; + +const PRIMES42: &'static [u64] = &[4398046511093, 4398046511087, 4398046511071, 4398046511051, + 4398046511039, 4398046510961, 4398046510943, 4398046510939, 4398046510889, 4398046510877, + 4398046510829, 4398046510787, 4398046510771, 4398046510751, 4398046510733, 4398046510721, + 4398046510643, 4398046510639, 4398046510597, 4398046510577, 4398046510547, 4398046510531, + 4398046510463, 4398046510397, 4398046510391, 4398046510379, 4398046510357, 4398046510331, + 4398046510327, 4398046510313, 4398046510283, 4398046510279, 4398046510217, 4398046510141, + 4398046510133, 4398046510103, 4398046510093, +]; + +const PRIMES43: &'static [u64] = &[8796093022151, 8796093022141, 8796093022091, 8796093022033, + 8796093021953, 8796093021941, 8796093021917, 8796093021899, 8796093021889, 8796093021839, + 8796093021803, 8796093021791, 8796093021769, 8796093021763, 8796093021743, 8796093021671, + 8796093021607, 8796093021587, 8796093021533, 8796093021523, 8796093021517, 8796093021493, + 8796093021467, 8796093021461, 8796093021449, 8796093021409, 8796093021407, 8796093021371, + 8796093021347, 8796093021337, 8796093021281, 8796093021269, +]; + +const PRIMES44: &'static [u64] = &[17592186044399, 17592186044299, 17592186044297, 17592186044287, + 17592186044273, 17592186044267, 17592186044129, 17592186044089, 17592186044057, 17592186044039, + 17592186043987, 17592186043921, 17592186043889, 17592186043877, 17592186043841, 17592186043829, + 17592186043819, 17592186043813, 17592186043807, 17592186043741, 17592186043693, 17592186043667, + 17592186043631, 17592186043591, 17592186043577, 17592186043547, 17592186043483, 17592186043451, + 17592186043433, 17592186043409, +]; + +const PRIMES45: &'static [u64] = &[35184372088777, 35184372088763, 35184372088751, 35184372088739, + 35184372088711, 35184372088699, 35184372088693, 35184372088673, 35184372088639, 35184372088603, + 35184372088571, 35184372088517, 35184372088493, 35184372088471, 35184372088403, 35184372088391, + 35184372088379, 35184372088363, 35184372088321, 35184372088319, 35184372088279, 35184372088259, + 35184372088249, 35184372088241, 35184372088223, 35184372088183, 35184372088097, 35184372088081, + 35184372088079, 35184372088051, 35184372088043, 35184372088039, 35184372087937, 35184372087929, + 35184372087923, 35184372087881, 35184372087877, 35184372087869, +]; + +const PRIMES46: &'static [u64] = &[70368744177643, 70368744177607, 70368744177601, 70368744177587, + 70368744177497, 70368744177467, 70368744177427, 70368744177377, 70368744177359, 70368744177353, + 70368744177331, 70368744177289, 70368744177283, 70368744177271, 70368744177257, 70368744177227, + 70368744177167, 70368744177113, 70368744177029, 70368744176959, 70368744176921, 70368744176909, + 70368744176879, 70368744176867, 70368744176833, 70368744176827, 70368744176807, 70368744176779, + 70368744176777, 70368744176729, 70368744176719, 70368744176711, +]; + +const PRIMES47: &'static [u64] = &[140737488355213, 140737488355201, 140737488355181, + 140737488355049, 140737488355031, 140737488354989, 140737488354893, 140737488354787, + 140737488354709, 140737488354679, 140737488354613, 140737488354557, 140737488354511, + 140737488354431, 140737488354413, 140737488354409, 140737488354373, 140737488354347, + 140737488354329, +]; + +const PRIMES48: &'static [u64] = &[281474976710597, 281474976710591, 281474976710567, + 281474976710563, 281474976710509, 281474976710491, 281474976710467, 281474976710423, + 281474976710413, 281474976710399, 281474976710339, 281474976710327, 281474976710287, + 281474976710197, 281474976710143, 281474976710131, 281474976710129, 281474976710107, + 281474976710089, 281474976710087, 281474976710029, 281474976709987, 281474976709891, + 281474976709859, 281474976709831, 281474976709757, 281474976709741, 281474976709711, + 281474976709649, 281474976709637, +]; + +const PRIMES49: &'static [u64] = &[562949953421231, 562949953421201, 562949953421189, + 562949953421173, 562949953421131, 562949953421111, 562949953421099, 562949953421047, + 562949953421029, 562949953420973, 562949953420871, 562949953420867, 562949953420837, + 562949953420793, 562949953420747, 562949953420741, 562949953420733, 562949953420727, + 562949953420609, 562949953420571, 562949953420559, 562949953420553, 562949953420523, + 562949953420507, 562949953420457, 562949953420403, 562949953420373, 562949953420369, + 562949953420343, 562949953420303, 562949953420297, +]; + +const PRIMES50: &'static [u64] = &[1125899906842597, 1125899906842589, 1125899906842573, + 1125899906842553, 1125899906842511, 1125899906842507, 1125899906842493, 1125899906842463, + 1125899906842429, 1125899906842391, 1125899906842357, 1125899906842283, 1125899906842273, + 1125899906842247, 1125899906842201, 1125899906842177, 1125899906842079, 1125899906842033, + 1125899906842021, 1125899906842013, 1125899906841973, 1125899906841971, 1125899906841959, + 1125899906841949, 1125899906841943, 1125899906841917, 1125899906841901, 1125899906841883, + 1125899906841859, 1125899906841811, 1125899906841803, 1125899906841751, 1125899906841713, + 1125899906841673, 1125899906841653, 1125899906841623, 1125899906841613, +];