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;