fix and slight optimization for factor

This commit builds upon @wikol's Pollard rho implementation.
It adds the following:

1. A generator for prime inverse tables. With these, we can do
   very fast divisibility tests (a single multiply and comparison)
   for small primes (presently, the first 1000 primes are in the
   table, which means all numbers of ~26 bits or less can be
   factored very quickly.

2. Always try prime inverse tables before jumping into Pollard's
   rho method or using trial division.

3. Since we have eliminated all small factors by the time we're
   done with the table division, only use slow trial division when
   the number is big enough to cause overflow issues in Pollard's
   rho, and jump out of trial division and into Pollard's rho as
   soon as the number is small enough.

4. Updates the Makefile to regenerate the prime table if it's not
   up-to-date.
This commit is contained in:
kwantam 2015-04-29 19:24:20 -04:00
parent 06b70877db
commit 6c4e967fc6
7 changed files with 875 additions and 117 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/src/*/gen_table
/build/
/target/
/tmp/

View file

@ -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)

1
src/factor/deps.mk Normal file
View file

@ -0,0 +1 @@
DEPLIBS += rand

View file

@ -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 <t.jameson.little@gmail.com>
* (c) Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
* 20150223 added Pollard rho method implementation
* (c) kwantam <kwantam@gmail.com>
* 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<u64> {
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<u64>) {
// 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<u64> {
let mut ret = Vec::new();
fn rho_pollard_factor(num: u64, factors: &mut Vec<u64>) {
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<u64>) {
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::<u64>() {
Ok(x) => x,
Err(e)=> { crash!(1, "{} not a number: {}", num_str, e); }
};
print_factors(num);
if let Err(e) = num_str.parse::<u64>().and_then(|x| Ok(print_factors(x))) {
show_warning!("{}: {}", num_str, e);
}
}
pub fn uumain(args: Vec<String>) -> 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<String>) -> 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

169
src/factor/gen_table.rs Normal file
View file

@ -0,0 +1,169 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) kwantam <kwantam@gmail.com>
*
* 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<Iterator<Item=u64>>,
filts: Vec<u64>,
}
impl Iterator for Sieve {
type Item = u64;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
#[inline]
fn next(&mut self) -> Option<u64> {
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<u64> {
let ret = Some(*s);
*s = *s + t;
ret
}
let next = next;
let odds_by_3 = Box::new(repeat(2).scan(3, next)) as Box<Iterator<Item=u64>>;
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<u64> {
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::<usize>().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 <kwantam@gmail.com>
*
* 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)] = &[
"##;

80
src/factor/numeric.rs Normal file
View file

@ -0,0 +1,80 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) Wiktor Kuropatwa <wiktor.kuropatwa@gmail.com>
*
* 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
}

517
src/factor/prime_table.rs Normal file
View file

@ -0,0 +1,517 @@
/*
* This file is part of the uutils coreutils package.
*
* (c) kwantam <kwantam@gmail.com>
*
* 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;