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, +];