use number_theory::NumberTheory;
 use number_theory::Mpz;


const EIGHT_WORD : [u64;256] = [ // 2^512 + k
	75, 145, 285, 727, 1105, 1147, 1273, 2743, 3177, 3913, 4597, 4933, 
	5527, 5695, 5821, 5857, 5941, 6273, 6301, 6325, 6333, 7111, 7471, 
	7693, 7735, 7741, 8721, 9231, 10161,10173, 10431, 10591, 11031, 
	11335, 12661, 13105, 13125, 13573, 14025, 14151, 14607, 15127, 15285,
	15441, 16797, 16951, 17553, 18787, 19615, 19833, 20155, 20571, 20845, 
	20887, 21033, 21331, 21475, 21627, 21733, 22707, 22801, 22993, 24451, 
	24505, 25387, 25557, 25611, 26205, 26215, 26391, 26557, 26721, 27061, 
	27075, 27355, 28221, 28351, 28405, 28473, 28743, 29425, 29607, 29827, 
	29931, 30001, 30207, 32073, 32227, 32463, 32835, 33223, 33325, 33511, 
	33657, 34231, 34423, 34621, 34743, 34851, 35035, 35847, 36145, 36385, 
	36415, 36601, 36663, 36883, 37423, 37515, 38163, 39061, 39291, 39313, 
	39373, 39481, 39513, 39727, 40455, 40845, 40921, 41217, 41277, 42097, 
	42321, 42351, 42517, 42705, 43345, 43363, 43525, 44013, 44137, 44695, 
	45375, 45511, 45813, 45927, 46041, 46195, 47041, 47193, 47341, 47601, 
	47691, 47731, 48307, 49005, 49167, 50031, 50055, 50517, 50701, 51097, 
	51273, 51813, 52897, 53397, 53517, 53883, 54891, 55323, 55671, 55923, 
	56145, 56257, 56331, 56425, 57073, 57433, 57481, 57517, 57861, 57877, 
	58641, 58963, 59317, 59443, 60225, 60283, 60345, 60543, 60855, 60921, 
	61207, 61287, 61591, 61887, 62497, 62511, 63061, 64245, 64351, 64831, 
	64917, 65107, 65217, 65421, 65473, 65475, 65671, 66345, 67015, 68511, 
	68703, 68983, 69057, 70681, 70993, 71737, 71853, 72223, 72391, 72423, 
	72781, 73453, 73515, 73627, 74001, 74041, 74163, 74701, 75297, 76147, 
	76221, 76531, 76617, 76851, 76981, 76995, 77061, 77257, 77743, 78045, 
	78135, 78187, 78211, 79017, 79293, 79441, 79773, 79843, 79917, 80023, 
	80575, 80743, 80757, 80911, 81117, 82105, 82377, 82401, 82941, 82975, 
	83125, 83203, 83473];
	
const TEN_WORD : [u64;256] = [ // 2^640 + k 
	115, 303, 391, 757, 1287, 1485, 2943, 3627, 3711, 3861, 3931, 4155, 4291,
	4425, 4683, 4903, 5343, 6507, 8133, 8373, 8677, 9055, 9061, 9543, 9873, 
	9885, 11883, 11937, 12573, 12795, 13917, 14083, 14913, 15171, 15177, 15837, 
	15855, 16647, 17965, 18615, 18823, 19233, 19681, 20143, 20311, 20785, 22863, 
	24313, 25441, 25491, 26235, 26635, 27243, 27541, 28161, 29295, 29397, 29541, 
	29553, 30823, 31875, 33363, 33561, 33831, 33847, 33961, 34047, 34327, 34975, 
	35515, 35647, 36303, 36495, 36661, 37213, 37257, 37353, 37687, 38137, 38415, 
	38863, 39013, 39103, 40975, 42115, 42303, 43135, 43633, 44011, 44047, 44295, 
	45867, 48453, 48615, 48645, 49437, 49651, 50283, 50395, 51013, 51027, 51615, 
	51921, 53407, 53901, 54907, 55003, 55723, 55761, 56637, 56823, 56997, 57061, 
	57451, 57495, 57655, 58131, 58317, 58743, 58765, 59137, 60085, 60091, 60151,
        60393, 60777, 62047, 62905, 63973, 64147, 64485, 64743, 65151, 65643, 65895, 
        66313, 66937, 67773, 69271, 69385, 69451, 69777, 70023, 70203, 71047, 71481, 
        71683, 72547, 73207, 73725, 73731, 73755, 73885, 74397, 74511, 74973, 75897, 
        75937, 76297, 76785, 76881, 76887, 78093, 78337, 78507, 78931, 79741, 80065, 
        81165, 81217, 81801, 81855, 82357, 82657, 82953, 83581, 83971, 84091, 84093, 
        84583, 85053, 85827, 87387, 87693, 88621, 88645, 89103, 89497, 90831, 90853, 
        91111, 91165, 92253, 93055, 93481, 93981, 94431, 94497, 94881, 95487, 95805, 
        96261, 97017, 97321, 97365, 97755, 97827, 98077, 98553, 98751, 98881, 99357, 
        99397, 99753, 100923, 100933, 101227, 101275, 101377, 101641, 101797, 101977, 
        102337, 102447, 102873, 103173, 104041, 104817, 105781, 106537, 106561, 106815, 
        107647, 108123, 108147, 108163, 108751, 108865, 110047, 110977, 111141, 111493, 
        112371, 112695, 113205, 113437, 113667, 113757, 113947, 114807, 115087, 115467, 
        116173, 116367, 116571, 116587
        ];	
        

const ONE_HUNDRED_WORD : [u64;256] = [// 2^6400 + k
	14931, 17961, 23313, 46333, 51345, 51643, 62533, 63927, 
	67245, 70585, 73485, 84477, 89851, 90325, 94285, 101487, 
	102841, 109033, 114073, 115207, 118101, 123511, 124141,
	125203, 126127, 127705, 129363, 136173, 145645, 147345, 
	152343, 153003, 154737, 155085, 156415, 166263, 171777, 
	172735, 173193, 174433, 174933, 175357, 175531, 184047,
	184393, 187413, 192483, 197653, 200215, 201411, 201813, 
	204001, 224823, 230121, 241335, 241507, 254587, 261223, 
	266907, 267625, 268131, 268375, 268671, 272385, 276307,
	277887, 278943, 283663, 287997, 290653, 292023, 292333, 
	292897, 303135, 306075, 310695, 311227, 312705, 317391, 
	317793, 318255, 321093, 323007, 324561, 328395, 329043,
	330277, 333193, 334767, 334975, 372351, 381297, 382215, 
	382615, 383971, 387765, 392547, 397123, 398043, 400095, 
	402583, 406641, 406837, 411037, 415515, 417897, 421921,
	435535, 440035, 441933, 444513, 451455, 459841, 465667, 
	466171, 481477, 490813, 493303, 498957, 503401, 503605, 
	507343, 509643, 511195, 511857, 514135, 514581, 515307,
	515335, 516037, 520851, 528133, 535033, 535381, 537361, 
	537667, 539611, 540135, 545187, 552765, 554151, 556693, 
	563797, 571747, 572137, 576055, 578011, 585577, 588253,
	599155, 602451, 602935, 604435, 604501, 612367, 613827, 
	616543, 617215, 619185, 625317, 646911, 649825, 663315, 
	674685, 675583, 685267, 686433, 691191, 692733, 694597,
	705853, 707491, 711117, 713517, 723055, 730185, 741321, 
	749757, 753693, 753883, 757395, 758221, 761365, 771753, 
	777973, 778257, 784093, 785065, 790755, 796021, 798273,
	808657, 816613, 817371, 823375, 824085, 826911, 828295, 
	830251, 831715, 837525, 839427, 839457, 840081, 840835, 
	844021, 846183, 847605, 852777, 858103, 864475, 867687,
	871371, 871875, 872095, 873915, 880525, 882247, 885945, 
	888243, 896211, 899635, 903295, 905911, 913215, 928341, 
	949921, 953533, 955131, 956577, 958237, 962271, 971217,
	973813, 983065, 987175, 989421, 997867, 1000495, 1010317, 
	1011927, 1013853, 1019593, 1024755, 1025373, 1035037, 
	1035783, 1036207, 1038577, 1039605, 1053373, 1057123,
	1058005, 1069677, 1074933, 1088961
     ];
     
  
const ONE_K_WORD : [u64;6] = [
  51277, 62301, 26235, 27307, 56763, 26235, 
];
 
 fn bench_prime(){
 
 let mut start = std::time::Instant::now();
 let mut count = 0u32;
 let k = Mpz::one().shl(512);
 for i in EIGHT_WORD{
 let p = k.ref_addition(&Mpz::from_u64(i));
   if p.is_prime(){
     count+=1;
   }
 }
 let mut stop = start.elapsed();
 assert_eq!(256,count);
 count = 0;
 println!("256 8-word (154 decimal digit) primes evaluated in {:?} ", stop);
 
 
  let k = Mpz::one().shl(640);
 start = std::time::Instant::now();
 for i in TEN_WORD{
  let p = k.ref_addition(&Mpz::from_u64(i));
   if p.is_prime(){
     count+=1;
   }
 }
 stop = start.elapsed();
 assert_eq!(256,count);
 count =0;
  println!("256 10-word (192 decimal digit) primes evaluated in {:?} ", stop); 
  
    let k = Mpz::one().shl(6400);
  start = std::time::Instant::now();
 for i in ONE_HUNDRED_WORD{
   let p = k.ref_addition(&Mpz::from_u64(i));
   if p.is_prime(){
     count+=1;
   }
 }
 stop = start.elapsed();
 assert_eq!(256,count);
 count=0;
  println!("256 100-word (1926 decimal digit) primes evaluated in {:?} ", stop); 
  
  /*
       let k = Mpz::one().shl(64000);
  start = std::time::Instant::now();
 for i in ONE_K_WORD{
    let p = k.ref_addition(&Mpz::from_u64(i));
   if p.is_prime(){
     count+=1;
   }
 }
 
 stop = start.elapsed();
 assert_eq!(6,count);
 count=0;
  println!("6 1000-word (19265 decimal digits) primes evaluated in {:?} ", stop);  
  */
 }
 fn main () {
 println!("For faster evaluation use \"parallel\" feature");
 bench_prime()
 }