1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

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/ /build/
/target/ /target/
/tmp/ /tmp/

View file

@ -30,7 +30,7 @@ RUSTCTESTFLAGS := $(RUSTCFLAGS)
# Handle config setup # Handle config setup
ifeq ($(ENABLE_LTO),y) ifeq ($(ENABLE_LTO),y)
RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -Z lto RUSTCBINFLAGS := $(RUSTCLIBFLAGS) -C lto
else else
RUSTCBINFLAGS := $(RUSTCLIBFLAGS) RUSTCBINFLAGS := $(RUSTCLIBFLAGS)
endif endif
@ -305,6 +305,9 @@ $(BUILDDIR)/mkuutils: mkuutils.rs | $(BUILDDIR)
$(SRCDIR)/cksum/crc_table.rs: $(SRCDIR)/cksum/gen_table.rs $(SRCDIR)/cksum/crc_table.rs: $(SRCDIR)/cksum/gen_table.rs
cd $(SRCDIR)/cksum && $(RUSTC) $(RUSTCBINFLAGS) gen_table.rs && ./gen_table && $(RM) gen_table 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: crates:
echo $(EXES) 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"] #![crate_name = "factor"]
#![feature(collections, core, old_io, rustc_private)] #![feature(rustc_private)]
/* /*
* This file is part of the uutils coreutils package. * This file is part of the uutils coreutils package.
* *
* (c) T. Jameson Little <t.jameson.little@gmail.com> * (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 * For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code. * that was distributed with this source code.
@ -14,111 +18,47 @@ extern crate getopts;
extern crate libc; extern crate libc;
extern crate rand; extern crate rand;
use std::vec::Vec; use numeric::*;
use std::old_io::BufferedReader; use prime_table::{P_INVS_U64, NEXT_PRIME};
use std::old_io::stdio::stdin_raw; use std::cmp::{max, min};
use std::cmp::{max,min}; use std::io::{stdin, BufRead, BufReader, Write};
use std::num::Wrapping;
use std::mem::swap; use std::mem::swap;
use rand::distributions::{IndependentSample, Range}; use rand::weak_rng;
use rand::distributions::{Range, IndependentSample};
#[path="../common/util.rs"] #[path="../common/util.rs"]
#[macro_use] #[macro_use]
mod util; mod util;
mod numeric;
mod prime_table;
static VERSION: &'static str = "1.0.0"; static VERSION: &'static str = "1.0.0";
static NAME: &'static str = "factor"; static NAME: &'static str = "factor";
// computes (a + b) % m using the russian peasant algorithm fn trial_division_slow(mut num: u64, factors: &mut Vec<u64>) {
fn multiply(mut a: u64, mut b: u64, m: u64) -> u64 { // assumption: this number has already been run through
let mut result = 0; // trial_division, which checks primes from the table.
while b > 0 { // The first candidate we need to check is NEXT_PRIME.
if b & 1 > 0 { let mut i = NEXT_PRIME;
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;
while i * i <= num { while i * i <= num {
while num % i == 0 { while num % i == 0 {
num /= i; 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; i += 2;
} }
if num > 1 { if num > 1 {
ret.push(num); factors.push(num);
} }
ret
} }
fn rho_pollard_pseudorandom_function(x: u64, a: u64, b: u64, num: u64) -> u64 { 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); 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);
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 { if d == num {
// Failure, retry with diffrent function // Failure, retry with diffrent function
x = range.ind_sample(&mut rng); 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> { fn rho_pollard_factor(num: u64, factors: &mut Vec<u64>) {
let mut ret = Vec::new();
if is_prime(num) { if is_prime(num) {
ret.push(num); factors.push(num);
return ret; return;
} }
let divisor = rho_pollard_find_divisor(num); let divisor = rho_pollard_find_divisor(num);
ret.push_all(rho_pollard_factor(divisor).as_slice()); rho_pollard_factor(divisor, factors);
ret.push_all(rho_pollard_factor(num/divisor).as_slice()); rho_pollard_factor(num / divisor, factors);
ret }
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) { fn print_factors(num: u64) {
print!("{}:", num); print!("{}:", num);
// Rho-Pollard is slower for small numbers and may cause 64-bit overflows let mut factors = Vec::new();
// for numbers bigger than 1 << 63, hence the constraints // we always start with table division, and go from there
let mut factors = if num < 1 << 63 && num > 1 << 40 { table_division(num, &mut factors);
rho_pollard_factor(num)
} else {
trial_division(num)
};
factors.sort(); factors.sort();
for fac in factors.iter() { for fac in factors.iter() {
print!(" {}", fac); print!(" {}", fac);
} }
@ -188,21 +172,18 @@ fn print_factors(num: u64) {
} }
fn print_factors_str(num_str: &str) { fn print_factors_str(num_str: &str) {
let num = match num_str.parse::<u64>() { if let Err(e) = num_str.parse::<u64>().and_then(|x| Ok(print_factors(x))) {
Ok(x) => x, show_warning!("{}: {}", num_str, e);
Err(e)=> { crash!(1, "{} not a number: {}", num_str, e); } }
};
print_factors(num);
} }
pub fn uumain(args: Vec<String>) -> i32 { pub fn uumain(args: Vec<String>) -> i32 {
let program = args[0].as_slice();
let opts = [ let opts = [
getopts::optflag("h", "help", "show this help message"), getopts::optflag("h", "help", "show this help message"),
getopts::optflag("v", "version", "print the version and exit"), 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, Ok(m) => m,
Err(f) => crash!(1, "Invalid options\n{}", f) 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} [NUMBER]...\n\
\t{program} [OPTION]\n\ \t{program} [OPTION]\n\
\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)); If none are specified, read from standard input.", &opts));
return 1; return 1;
} }
if matches.opt_present("version") { if matches.opt_present("version") {
println!("{} {}", program, VERSION); println!("{} {}", &args[0][..], VERSION);
return 0; return 0;
} }
if matches.free.is_empty() { if matches.free.is_empty() {
for line in BufferedReader::new(stdin_raw()).lines() { for line in BufReader::new(stdin()).lines() {
print_factors_str(line.unwrap().as_slice().trim()); for number in line.unwrap().split_whitespace() {
print_factors_str(number);
}
} }
} else { } else {
for num_str in matches.free.iter() { for num_str in matches.free.iter() {
print_factors_str(num_str.as_slice()); print_factors_str(num_str);
} }
} }
0 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;