1#/* 2# * Copyright (C) 2017 - This file is part of libecc project 3# * 4# * Authors: 5# * Ryad BENADJILA <ryadbenadjila@gmail.com> 6# * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7# * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8# * 9# * Contributors: 10# * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11# * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12# * 13# * This software is licensed under a dual BSD and GPL v2 license. 14# * See LICENSE file at the root folder of the project. 15# */ 16#! /usr/bin/env python 17 18import random, sys, re, math, socket, os, select, signal 19from datetime import datetime 20 21# Pre generated primes 22first_primes_list = [ 23 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 24 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 25 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 26 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 27 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 28 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 29 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 30 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 31 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 32 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 33 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 34 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 35 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 36 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 37 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 38 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 39 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 40 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 41 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 42 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 43 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 44 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 45 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 46 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 47 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 48 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 49 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 50 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 51 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 52 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 53 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 54 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 55 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 56 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 57 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 58 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 59 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 60 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 61 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 62 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 63 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 64 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 65 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 66 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 67 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 68 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 69 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 70 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 71 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 72 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 73 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 74 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 75 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 76 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 77 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 78 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 79 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 80 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 81 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 82 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 83 4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 84 4507, 4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 85 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 86 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 87 4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 88 4861, 4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 89 4943, 4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999, 5003, 90 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 91 5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 92 5189, 5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 93 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 94 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 95 5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 96 5527, 5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 97 5641, 5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 98 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 99 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 100 5861, 5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 101 5953, 5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 102 6067, 6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 103 6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 104 6229, 6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 105 6311, 6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 106 6373, 6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 107 6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 108 6577, 6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 109 6679, 6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 110 6763, 6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 111 6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 112 6947, 6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 113 7001, 7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 114 7109, 7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 115 7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 116 7307, 7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 117 7417, 7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 118 7507, 7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 119 7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 120 7649, 7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 121 7727, 7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 122 7841, 7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 123 7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 124 8039, 8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 125 8117, 8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 126 8221, 8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 127 8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 128 8389, 8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 129 8513, 8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 130 8599, 8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 131 8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 132 8747, 8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 133 8837, 8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 134 8933, 8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 135 9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 136 9127, 9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 137 9203, 9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 138 9293, 9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 139 9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 140 9461, 9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 141 9539, 9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 142 9643, 9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 143 9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 144 9817, 9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 145 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007, 146 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 147 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 148 10181, 10193, 10211, 10223, 10243, 10247, 10253, 10259, 10267, 10271, 149 10273, 10289, 10301, 10303, 10313, 10321, 10331, 10333, 10337, 10343, 150 10357, 10369, 10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459, 151 10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531, 10559, 10567, 152 10589, 10597, 10601, 10607, 10613, 10627, 10631, 10639, 10651, 10657, 153 10663, 10667, 10687, 10691, 10709, 10711, 10723, 10729, 10733, 10739, 154 10753, 10771, 10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859, 155 10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937, 10939, 10949, 156 10957, 10973, 10979, 10987, 10993, 11003, 11027, 11047, 11057, 11059, 157 11069, 11071, 11083, 11087, 11093, 11113, 11117, 11119, 11131, 11149, 158 11159, 11161, 11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251, 159 11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317, 11321, 11329, 160 11351, 11353, 11369, 11383, 11393, 11399, 11411, 11423, 11437, 11443, 161 11447, 11467, 11471, 11483, 11489, 11491, 11497, 11503, 11519, 11527, 162 11549, 11551, 11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657, 163 11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731, 11743, 11777, 164 11779, 11783, 11789, 11801, 11807, 11813, 11821, 11827, 11831, 11833, 165 11839, 11863, 11867, 11887, 11897, 11903, 11909, 11923, 11927, 11933, 166 11939, 11941, 11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011, 167 12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101, 12107, 12109, 168 12113, 12119, 12143, 12149, 12157, 12161, 12163, 12197, 12203, 12211, 169 12227, 12239, 12241, 12251, 12253, 12263, 12269, 12277, 12281, 12289, 170 12301, 12323, 12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401, 171 12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473, 12479, 12487, 172 12491, 12497, 12503, 12511, 12517, 12527, 12539, 12541, 12547, 12553, 173 12569, 12577, 12583, 12589, 12601, 12611, 12613, 12619, 12637, 12641, 174 12647, 12653, 12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739, 175 12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821, 12823, 12829, 176 12841, 12853, 12889, 12893, 12899, 12907, 12911, 12917, 12919, 12923, 177 12941, 12953, 12959, 12967, 12973, 12979, 12983, 13001, 13003, 13007, 178 13009, 13033, 13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109, 179 13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177, 13183, 13187, 180 13217, 13219, 13229, 13241, 13249, 13259, 13267, 13291, 13297, 13309, 181 13313, 13327, 13331, 13337, 13339, 13367, 13381, 13397, 13399, 13411, 182 13417, 13421, 13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499, 183 13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597, 13613, 13619, 184 13627, 13633, 13649, 13669, 13679, 13681, 13687, 13691, 13693, 13697, 185 13709, 13711, 13721, 13723, 13729, 13751, 13757, 13759, 13763, 13781, 186 13789, 13799, 13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879, 187 13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933, 13963, 13967, 188 13997, 13999, 14009, 14011, 14029, 14033, 14051, 14057, 14071, 14081, 189 14083, 14087, 14107, 14143, 14149, 14153, 14159, 14173, 14177, 14197, 190 14207, 14221, 14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323, 191 14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407, 14411, 14419, 192 14423, 14431, 14437, 14447, 14449, 14461, 14479, 14489, 14503, 14519, 193 14533, 14537, 14543, 14549, 14551, 14557, 14561, 14563, 14591, 14593, 194 14621, 14627, 14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699, 195 14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753, 14759, 14767, 196 14771, 14779, 14783, 14797, 14813, 14821, 14827, 14831, 14843, 14851, 197 14867, 14869, 14879, 14887, 14891, 14897, 14923, 14929, 14939, 14947, 198 14951, 14957, 14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073, 199 15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137, 15139, 15149, 200 15161, 15173, 15187, 15193, 15199, 15217, 15227, 15233, 15241, 15259, 201 15263, 15269, 15271, 15277, 15287, 15289, 15299, 15307, 15313, 15319, 202 15329, 15331, 15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401, 203 15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473, 15493, 15497, 204 15511, 15527, 15541, 15551, 15559, 15569, 15581, 15583, 15601, 15607, 205 15619, 15629, 15641, 15643, 15647, 15649, 15661, 15667, 15671, 15679, 206 15683, 15727, 15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773, 207 15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859, 15877, 15881, 208 15887, 15889, 15901, 15907, 15913, 15919, 15923, 15937, 15959, 15971, 209 15973, 15991, 16001, 16007, 16033, 16057, 16061, 16063, 16067, 16069, 210 16073, 16087, 16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183, 211 16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249, 16253, 16267, 212 16273, 16301, 16319, 16333, 16339, 16349, 16361, 16363, 16369, 16381, 213 16411, 16417, 16421, 16427, 16433, 16447, 16451, 16453, 16477, 16481, 214 16487, 16493, 16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603, 215 16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661, 16673, 16691, 216 16693, 16699, 16703, 16729, 16741, 16747, 16759, 16763, 16787, 16811, 217 16823, 16829, 16831, 16843, 16871, 16879, 16883, 16889, 16901, 16903, 218 16921, 16927, 16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993, 219 17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053, 17077, 17093, 220 17099, 17107, 17117, 17123, 17137, 17159, 17167, 17183, 17189, 17191, 221 17203, 17207, 17209, 17231, 17239, 17257, 17291, 17293, 17299, 17317, 222 17321, 17327, 17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389, 223 17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467, 17471, 17477, 224 17483, 17489, 17491, 17497, 17509, 17519, 17539, 17551, 17569, 17573, 225 17579, 17581, 17597, 17599, 17609, 17623, 17627, 17657, 17659, 17669, 226 17681, 17683, 17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783, 227 17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863, 17881, 17891, 228 17903, 17909, 17911, 17921, 17923, 17929, 17939, 17957, 17959, 17971, 229 17977, 17981, 17987, 17989, 18013, 18041, 18043, 18047, 18049, 18059, 230 18061, 18077, 18089, 18097, 18119, 18121, 18127, 18131, 18133, 18143, 231 18149, 18169, 18181, 18191, 18199, 18211, 18217, 18223, 18229, 18233, 232 18251, 18253, 18257, 18269, 18287, 18289, 18301, 18307, 18311, 18313, 233 18329, 18341, 18353, 18367, 18371, 18379, 18397, 18401, 18413, 18427, 234 18433, 18439, 18443, 18451, 18457, 18461, 18481, 18493, 18503, 18517, 235 18521, 18523, 18539, 18541, 18553, 18583, 18587, 18593, 18617, 18637, 236 18661, 18671, 18679, 18691, 18701, 18713, 18719, 18731, 18743, 18749, 237 18757, 18773, 18787, 18793, 18797, 18803, 18839, 18859, 18869, 18899, 238 18911, 18913, 18917, 18919, 18947, 18959, 18973, 18979, 19001, 19009, 239 19013, 19031, 19037, 19051, 19069, 19073, 19079, 19081, 19087, 19121, 240 19139, 19141, 19157, 19163, 19181, 19183, 19207, 19211, 19213, 19219, 241 19231, 19237, 19249, 19259, 19267, 19273, 19289, 19301, 19309, 19319, 242 19333, 19373, 19379, 19381, 19387, 19391, 19403, 19417, 19421, 19423, 243 19427, 19429, 19433, 19441, 19447, 19457, 19463, 19469, 19471, 19477, 244 19483, 19489, 19501, 19507, 19531, 19541, 19543, 19553, 19559, 19571, 245 19577, 19583, 19597, 19603, 19609, 19661, 19681, 19687, 19697, 19699, 246 19709, 19717, 19727, 19739, 19751, 19753, 19759, 19763, 19777, 19793, 247 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, 248 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, 249 19993, 19997, 20011, 20021, 20023, 20029, 20047, 20051, 20063, 20071, 250 20089, 20101, 20107, 20113, 20117, 20123, 20129, 20143, 20147, 20149, 251 20161, 20173, 20177, 20183, 20201, 20219, 20231, 20233, 20249, 20261, 252 20269, 20287, 20297, 20323, 20327, 20333, 20341, 20347, 20353, 20357, 253 20359, 20369, 20389, 20393, 20399, 20407, 20411, 20431, 20441, 20443, 254 20477, 20479, 20483, 20507, 20509, 20521, 20533, 20543, 20549, 20551, 255 20563, 20593, 20599, 20611, 20627, 20639, 20641, 20663, 20681, 20693, 256 20707, 20717, 20719, 20731, 20743, 20747, 20749, 20753, 20759, 20771, 257 20773, 20789, 20807, 20809, 20849, 20857, 20873, 20879, 20887, 20897, 258 20899, 20903, 20921, 20929, 20939, 20947, 20959, 20963, 20981, 20983, 259 21001, 21011, 21013, 21017, 21019, 21023, 21031, 21059, 21061, 21067, 260 21089, 21101, 21107, 21121, 21139, 21143, 21149, 21157, 21163, 21169, 261 21179, 21187, 21191, 21193, 21211, 21221, 21227, 21247, 21269, 21277, 262 21283, 21313, 21317, 21319, 21323, 21341, 21347, 21377, 21379, 21383, 263 21391, 21397, 21401, 21407, 21419, 21433, 21467, 21481, 21487, 21491, 264 21493, 21499, 21503, 21517, 21521, 21523, 21529, 21557, 21559, 21563, 265 21569, 21577, 21587, 21589, 21599, 21601, 21611, 21613, 21617, 21647, 266 21649, 21661, 21673, 21683, 21701, 21713, 21727, 21737, 21739, 21751, 267 21757, 21767, 21773, 21787, 21799, 21803, 21817, 21821, 21839, 21841, 268 21851, 21859, 21863, 21871, 21881, 21893, 21911, 21929, 21937, 21943, 269 21961, 21977, 21991, 21997, 22003, 22013, 22027, 22031, 22037, 22039, 270 22051, 22063, 22067, 22073, 22079, 22091, 22093, 22109, 22111, 22123, 271 22129, 22133, 22147, 22153, 22157, 22159, 22171, 22189, 22193, 22229, 272 22247, 22259, 22271, 22273, 22277, 22279, 22283, 22291, 22303, 22307, 273 22343, 22349, 22367, 22369, 22381, 22391, 22397, 22409, 22433, 22441, 274 22447, 22453, 22469, 22481, 22483, 22501, 22511, 22531, 22541, 22543, 275 22549, 22567, 22571, 22573, 22613, 22619, 22621, 22637, 22639, 22643, 276 22651, 22669, 22679, 22691, 22697, 22699, 22709, 22717, 22721, 22727, 277 22739, 22741, 22751, 22769, 22777, 22783, 22787, 22807, 22811, 22817, 278 22853, 22859, 22861, 22871, 22877, 22901, 22907, 22921, 22937, 22943, 279 22961, 22963, 22973, 22993, 23003, 23011, 23017, 23021, 23027, 23029, 280 23039, 23041, 23053, 23057, 23059, 23063, 23071, 23081, 23087, 23099, 281 23117, 23131, 23143, 23159, 23167, 23173, 23189, 23197, 23201, 23203, 282 23209, 23227, 23251, 23269, 23279, 23291, 23293, 23297, 23311, 23321, 283 23327, 23333, 23339, 23357, 23369, 23371, 23399, 23417, 23431, 23447, 284 23459, 23473, 23497, 23509, 23531, 23537, 23539, 23549, 23557, 23561, 285 23563, 23567, 23581, 23593, 23599, 23603, 23609, 23623, 23627, 23629, 286 23633, 23663, 23669, 23671, 23677, 23687, 23689, 23719, 23741, 23743, 287 23747, 23753, 23761, 23767, 23773, 23789, 23801, 23813, 23819, 23827, 288 23831, 23833, 23857, 23869, 23873, 23879, 23887, 23893, 23899, 23909, 289 23911, 23917, 23929, 23957, 23971, 23977, 23981, 23993, 24001, 24007, 290 24019, 24023, 24029, 24043, 24049, 24061, 24071, 24077, 24083, 24091, 291 24097, 24103, 24107, 24109, 24113, 24121, 24133, 24137, 24151, 24169, 292 24179, 24181, 24197, 24203, 24223, 24229, 24239, 24247, 24251, 24281, 293 24317, 24329, 24337, 24359, 24371, 24373, 24379, 24391, 24407, 24413, 294 24419, 24421, 24439, 24443, 24469, 24473, 24481, 24499, 24509, 24517, 295 24527, 24533, 24547, 24551, 24571, 24593, 24611, 24623, 24631, 24659, 296 24671, 24677, 24683, 24691, 24697, 24709, 24733, 24749, 24763, 24767, 297 24781, 24793, 24799, 24809, 24821, 24841, 24847, 24851, 24859, 24877, 298 24889, 24907, 24917, 24919, 24923, 24943, 24953, 24967, 24971, 24977, 299 24979, 24989, 25013, 25031, 25033, 25037, 25057, 25073, 25087, 25097, 300 25111, 25117, 25121, 25127, 25147, 25153, 25163, 25169, 25171, 25183, 301 25189, 25219, 25229, 25237, 25243, 25247, 25253, 25261, 25301, 25303, 302 25307, 25309, 25321, 25339, 25343, 25349, 25357, 25367, 25373, 25391, 303 25409, 25411, 25423, 25439, 25447, 25453, 25457, 25463, 25469, 25471, 304 25523, 25537, 25541, 25561, 25577, 25579, 25583, 25589, 25601, 25603, 305 25609, 25621, 25633, 25639, 25643, 25657, 25667, 25673, 25679, 25693, 306 25703, 25717, 25733, 25741, 25747, 25759, 25763, 25771, 25793, 25799, 307 25801, 25819, 25841, 25847, 25849, 25867, 25873, 25889, 25903, 25913, 308 25919, 25931, 25933, 25939, 25943, 25951, 25969, 25981, 25997, 25999, 309 26003, 26017, 26021, 26029, 26041, 26053, 26083, 26099, 26107, 26111, 310 26113, 26119, 26141, 26153, 26161, 26171, 26177, 26183, 26189, 26203, 311 26209, 26227, 26237, 26249, 26251, 26261, 26263, 26267, 26293, 26297, 312 26309, 26317, 26321, 26339, 26347, 26357, 26371, 26387, 26393, 26399, 313 26407, 26417, 26423, 26431, 26437, 26449, 26459, 26479, 26489, 26497, 314 26501, 26513, 26539, 26557, 26561, 26573, 26591, 26597, 26627, 26633, 315 26641, 26647, 26669, 26681, 26683, 26687, 26693, 26699, 26701, 26711, 316 26713, 26717, 26723, 26729, 26731, 26737, 26759, 26777, 26783, 26801, 317 26813, 26821, 26833, 26839, 26849, 26861, 26863, 26879, 26881, 26891, 318 26893, 26903, 26921, 26927, 26947, 26951, 26953, 26959, 26981, 26987, 319 26993, 27011, 27017, 27031, 27043, 27059, 27061, 27067, 27073, 27077, 320 27091, 27103, 27107, 27109, 27127, 27143, 27179, 27191, 27197, 27211, 321 27239, 27241, 27253, 27259, 27271, 27277, 27281, 27283, 27299, 27329, 322 27337, 27361, 27367, 27397, 27407, 27409, 27427, 27431, 27437, 27449, 323 27457, 27479, 27481, 27487, 27509, 27527, 27529, 27539, 27541, 27551, 324 27581, 27583, 27611, 27617, 27631, 27647, 27653, 27673, 27689, 27691, 325 27697, 27701, 27733, 27737, 27739, 27743, 27749, 27751, 27763, 27767, 326 27773, 27779, 27791, 27793, 27799, 27803, 27809, 27817, 27823, 27827, 327 27847, 27851, 27883, 27893, 27901, 27917, 27919, 27941, 27943, 27947, 328 27953, 27961, 27967, 27983, 27997, 28001, 28019, 28027, 28031, 28051, 329 28057, 28069, 28081, 28087, 28097, 28099, 28109, 28111, 28123, 28151, 330 28163, 28181, 28183, 28201, 28211, 28219, 28229, 28277, 28279, 28283, 331 28289, 28297, 28307, 28309, 28319, 28349, 28351, 28387, 28393, 28403, 332 28409, 28411, 28429, 28433, 28439, 28447, 28463, 28477, 28493, 28499, 333 28513, 28517, 28537, 28541, 28547, 28549, 28559, 28571, 28573, 28579, 334 28591, 28597, 28603, 28607, 28619, 28621, 28627, 28631, 28643, 28649, 335 28657, 28661, 28663, 28669, 28687, 28697, 28703, 28711, 28723, 28729, 336 28751, 28753, 28759, 28771, 28789, 28793, 28807, 28813, 28817, 28837, 337 28843, 28859, 28867, 28871, 28879, 28901, 28909, 28921, 28927, 28933, 338 28949, 28961, 28979, 29009, 29017, 29021, 29023, 29027, 29033, 29059, 339 29063, 29077, 29101, 29123, 29129, 29131, 29137, 29147, 29153, 29167, 340 29173, 29179, 29191, 29201, 29207, 29209, 29221, 29231, 29243, 29251, 341 29269, 29287, 29297, 29303, 29311, 29327, 29333, 29339, 29347, 29363, 342 29383, 29387, 29389, 29399, 29401, 29411, 29423, 29429, 29437, 29443, 343 29453, 29473, 29483, 29501, 29527, 29531, 29537, 29567, 29569, 29573, 344 29581, 29587, 29599, 29611, 29629, 29633, 29641, 29663, 29669, 29671, 345 29683, 29717, 29723, 29741, 29753, 29759, 29761, 29789, 29803, 29819, 346 29833, 29837, 29851, 29863, 29867, 29873, 29879, 29881, 29917, 29921, 347 29927, 29947, 29959, 29983, 29989, 30011, 30013, 30029, 30047, 30059, 348 30071, 30089, 30091, 30097, 30103, 30109, 30113, 30119, 30133, 30137, 349 30139, 30161, 30169, 30181, 30187, 30197, 30203, 30211, 30223, 30241, 350 30253, 30259, 30269, 30271, 30293, 30307, 30313, 30319, 30323, 30341, 351 30347, 30367, 30389, 30391, 30403, 30427, 30431, 30449, 30467, 30469, 352 30491, 30493, 30497, 30509, 30517, 30529, 30539, 30553, 30557, 30559, 353 30577, 30593, 30631, 30637, 30643, 30649, 30661, 30671, 30677, 30689, 354 30697, 30703, 30707, 30713, 30727, 30757, 30763, 30773, 30781, 30803, 355 30809, 30817, 30829, 30839, 30841, 30851, 30853, 30859, 30869, 30871, 356 30881, 30893, 30911, 30931, 30937, 30941, 30949, 30971, 30977, 30983, 357 31013, 31019, 31033, 31039, 31051, 31063, 31069, 31079, 31081, 31091, 358 31121, 31123, 31139, 31147, 31151, 31153, 31159, 31177, 31181, 31183, 359 31189, 31193, 31219, 31223, 31231, 31237, 31247, 31249, 31253, 31259, 360 31267, 31271, 31277, 31307, 31319, 31321, 31327, 31333, 31337, 31357, 361 31379, 31387, 31391, 31393, 31397, 31469, 31477, 31481, 31489, 31511, 362 31513, 31517, 31531, 31541, 31543, 31547, 31567, 31573, 31583, 31601, 363 31607, 31627, 31643, 31649, 31657, 31663, 31667, 31687, 31699, 31721, 364 31723, 31727, 31729, 31741, 31751, 31769, 31771, 31793, 31799, 31817, 365 31847, 31849, 31859, 31873, 31883, 31891, 31907, 31957, 31963, 31973, 366 31981, 31991, 32003, 32009, 32027, 32029, 32051, 32057, 32059, 32063, 367 32069, 32077, 32083, 32089, 32099, 32117, 32119, 32141, 32143, 32159, 368 32173, 32183, 32189, 32191, 32203, 32213, 32233, 32237, 32251, 32257, 369 32261, 32297, 32299, 32303, 32309, 32321, 32323, 32327, 32341, 32353, 370 32359, 32363, 32369, 32371, 32377, 32381, 32401, 32411, 32413, 32423, 371 32429, 32441, 32443, 32467, 32479, 32491, 32497, 32503, 32507, 32531, 372 32533, 32537, 32561, 32563, 32569, 32573, 32579, 32587, 32603, 32609, 373 32611, 32621, 32633, 32647, 32653, 32687, 32693, 32707, 32713, 32717, 374 32719, 32749, 32771, 32779, 32783, 32789, 32797, 32801, 32803, 32831, 375 32833, 32839, 32843, 32869, 32887, 32909, 32911, 32917, 32933, 32939, 376 32941, 32957, 32969, 32971, 32983, 32987, 32993, 32999, 33013, 33023, 377 33029, 33037, 33049, 33053, 33071, 33073, 33083, 33091, 33107, 33113, 378 33119, 33149, 33151, 33161, 33179, 33181, 33191, 33199, 33203, 33211, 379 33223, 33247, 33287, 33289, 33301, 33311, 33317, 33329, 33331, 33343, 380 33347, 33349, 33353, 33359, 33377, 33391, 33403, 33409, 33413, 33427, 381 33457, 33461, 33469, 33479, 33487, 33493, 33503, 33521, 33529, 33533, 382 33547, 33563, 33569, 33577, 33581, 33587, 33589, 33599, 33601, 33613, 383 33617, 33619, 33623, 33629, 33637, 33641, 33647, 33679, 33703, 33713, 384 33721, 33739, 33749, 33751, 33757, 33767, 33769, 33773, 33791, 33797, 385 33809, 33811, 33827, 33829, 33851, 33857, 33863, 33871, 33889, 33893, 386 33911, 33923, 33931, 33937, 33941, 33961, 33967, 33997, 34019, 34031, 387 34033, 34039, 34057, 34061, 34123, 34127, 34129, 34141, 34147, 34157, 388 34159, 34171, 34183, 34211, 34213, 34217, 34231, 34253, 34259, 34261, 389 34267, 34273, 34283, 34297, 34301, 34303, 34313, 34319, 34327, 34337, 390 34351, 34361, 34367, 34369, 34381, 34403, 34421, 34429, 34439, 34457, 391 34469, 34471, 34483, 34487, 34499, 34501, 34511, 34513, 34519, 34537, 392 34543, 34549, 34583, 34589, 34591, 34603, 34607, 34613, 34631, 34649, 393 34651, 34667, 34673, 34679, 34687, 34693, 34703, 34721, 34729, 34739, 394 34747, 34757, 34759, 34763, 34781, 34807, 34819, 34841, 34843, 34847, 395 34849, 34871, 34877, 34883, 34897, 34913, 34919, 34939, 34949, 34961, 396 34963, 34981, 35023, 35027, 35051, 35053, 35059, 35069, 35081, 35083, 397 35089, 35099, 35107, 35111, 35117, 35129, 35141, 35149, 35153, 35159, 398 35171, 35201, 35221, 35227, 35251, 35257, 35267, 35279, 35281, 35291, 399 35311, 35317, 35323, 35327, 35339, 35353, 35363, 35381, 35393, 35401, 400 35407, 35419, 35423, 35437, 35447, 35449, 35461, 35491, 35507, 35509, 401 35521, 35527, 35531, 35533, 35537, 35543, 35569, 35573, 35591, 35593, 402 35597, 35603, 35617, 35671, 35677, 35729, 35731, 35747, 35753, 35759, 403 35771, 35797, 35801, 35803, 35809, 35831, 35837, 35839, 35851, 35863, 404 35869, 35879, 35897, 35899, 35911, 35923, 35933, 35951, 35963, 35969, 405 35977, 35983, 35993, 35999, 36007, 36011, 36013, 36017, 36037, 36061, 406 36067, 36073, 36083, 36097, 36107, 36109, 36131, 36137, 36151, 36161, 407 36187, 36191, 36209, 36217, 36229, 36241, 36251, 36263, 36269, 36277, 408 36293, 36299, 36307, 36313, 36319, 36341, 36343, 36353, 36373, 36383, 409 36389, 36433, 36451, 36457, 36467, 36469, 36473, 36479, 36493, 36497, 410 36523, 36527, 36529, 36541, 36551, 36559, 36563, 36571, 36583, 36587, 411 36599, 36607, 36629, 36637, 36643, 36653, 36671, 36677, 36683, 36691, 412 36697, 36709, 36713, 36721, 36739, 36749, 36761, 36767, 36779, 36781, 413 36787, 36791, 36793, 36809, 36821, 36833, 36847, 36857, 36871, 36877, 414 36887, 36899, 36901, 36913, 36919, 36923, 36929, 36931, 36943, 36947, 415 36973, 36979, 36997, 37003, 37013, 37019, 37021, 37039, 37049, 37057, 416 37061, 37087, 37097, 37117, 37123, 37139, 37159, 37171, 37181, 37189, 417 37199, 37201, 37217, 37223, 37243, 37253, 37273, 37277, 37307, 37309, 418 37313, 37321, 37337, 37339, 37357, 37361, 37363, 37369, 37379, 37397, 419 37409, 37423, 37441, 37447, 37463, 37483, 37489, 37493, 37501, 37507, 420 37511, 37517, 37529, 37537, 37547, 37549, 37561, 37567, 37571, 37573, 421 37579, 37589, 37591, 37607, 37619, 37633, 37643, 37649, 37657, 37663, 422 37691, 37693, 37699, 37717, 37747, 37781, 37783, 37799, 37811, 37813, 423 37831, 37847, 37853, 37861, 37871, 37879, 37889, 37897, 37907, 37951, 424 37957, 37963, 37967, 37987, 37991, 37993, 37997, 38011, 38039, 38047, 425 38053, 38069, 38083, 38113, 38119, 38149, 38153, 38167, 38177, 38183, 426 38189, 38197, 38201, 38219, 38231, 38237, 38239, 38261, 38273, 38281, 427 38287, 38299, 38303, 38317, 38321, 38327, 38329, 38333, 38351, 38371, 428 38377, 38393, 38431, 38447, 38449, 38453, 38459, 38461, 38501, 38543, 429 38557, 38561, 38567, 38569, 38593, 38603, 38609, 38611, 38629, 38639, 430 38651, 38653, 38669, 38671, 38677, 38693, 38699, 38707, 38711, 38713, 431 38723, 38729, 38737, 38747, 38749, 38767, 38783, 38791, 38803, 38821, 432 38833, 38839, 38851, 38861, 38867, 38873, 38891, 38903, 38917, 38921, 433 38923, 38933, 38953, 38959, 38971, 38977, 38993, 39019, 39023, 39041, 434 39043, 39047, 39079, 39089, 39097, 39103, 39107, 39113, 39119, 39133, 435 39139, 39157, 39161, 39163, 39181, 39191, 39199, 39209, 39217, 39227, 436 39229, 39233, 39239, 39241, 39251, 39293, 39301, 39313, 39317, 39323, 437 39341, 39343, 39359, 39367, 39371, 39373, 39383, 39397, 39409, 39419, 438 39439, 39443, 39451, 39461, 39499, 39503, 39509, 39511, 39521, 39541, 439 39551, 39563, 39569, 39581, 39607, 39619, 39623, 39631, 39659, 39667, 440 39671, 39679, 39703, 39709, 39719, 39727, 39733, 39749, 39761, 39769, 441 39779, 39791, 39799, 39821, 39827, 39829, 39839, 39841, 39847, 39857, 442 39863, 39869, 39877, 39883, 39887, 39901, 39929, 39937, 39953, 39971, 443 39979, 39983, 39989, 40009, 40013, 40031, 40037, 40039, 40063, 40087, 444 40093, 40099, 40111, 40123, 40127, 40129, 40151, 40153, 40163, 40169, 445 40177, 40189, 40193, 40213, 40231, 40237, 40241, 40253, 40277, 40283, 446 40289, 40343, 40351, 40357, 40361, 40387, 40423, 40427, 40429, 40433, 447 40459, 40471, 40483, 40487, 40493, 40499, 40507, 40519, 40529, 40531, 448 40543, 40559, 40577, 40583, 40591, 40597, 40609, 40627, 40637, 40639, 449 40693, 40697, 40699, 40709, 40739, 40751, 40759, 40763, 40771, 40787, 450 40801, 40813, 40819, 40823, 40829, 40841, 40847, 40849, 40853, 40867, 451 40879, 40883, 40897, 40903, 40927, 40933, 40939, 40949, 40961, 40973, 452 40993, 41011, 41017, 41023, 41039, 41047, 41051, 41057, 41077, 41081, 453 41113, 41117, 41131, 41141, 41143, 41149, 41161, 41177, 41179, 41183, 454 41189, 41201, 41203, 41213, 41221, 41227, 41231, 41233, 41243, 41257, 455 41263, 41269, 41281, 41299, 41333, 41341, 41351, 41357, 41381, 41387, 456 41389, 41399, 41411, 41413, 41443, 41453, 41467, 41479, 41491, 41507, 457 41513, 41519, 41521, 41539, 41543, 41549, 41579, 41593, 41597, 41603, 458 41609, 41611, 41617, 41621, 41627, 41641, 41647, 41651, 41659, 41669, 459 41681, 41687, 41719, 41729, 41737, 41759, 41761, 41771, 41777, 41801, 460 41809, 41813, 41843, 41849, 41851, 41863, 41879, 41887, 41893, 41897, 461 41903, 41911, 41927, 41941, 41947, 41953, 41957, 41959, 41969, 41981, 462 41983, 41999, 42013, 42017, 42019, 42023, 42043, 42061, 42071, 42073, 463 42083, 42089, 42101, 42131, 42139, 42157, 42169, 42179, 42181, 42187, 464 42193, 42197, 42209, 42221, 42223, 42227, 42239, 42257, 42281, 42283, 465 42293, 42299, 42307, 42323, 42331, 42337, 42349, 42359, 42373, 42379, 466 42391, 42397, 42403, 42407, 42409, 42433, 42437, 42443, 42451, 42457, 467 42461, 42463, 42467, 42473, 42487, 42491, 42499, 42509, 42533, 42557, 468 42569, 42571, 42577, 42589, 42611, 42641, 42643, 42649, 42667, 42677, 469 42683, 42689, 42697, 42701, 42703, 42709, 42719, 42727, 42737, 42743, 470 42751, 42767, 42773, 42787, 42793, 42797, 42821, 42829, 42839, 42841, 471 42853, 42859, 42863, 42899, 42901, 42923, 42929, 42937, 42943, 42953, 472 42961, 42967, 42979, 42989, 43003, 43013, 43019, 43037, 43049, 43051, 473 43063, 43067, 43093, 43103, 43117, 43133, 43151, 43159, 43177, 43189, 474 43201, 43207, 43223, 43237, 43261, 43271, 43283, 43291, 43313, 43319, 475 43321, 43331, 43391, 43397, 43399, 43403, 43411, 43427, 43441, 43451, 476 43457, 43481, 43487, 43499, 43517, 43541, 43543, 43573, 43577, 43579, 477 43591, 43597, 43607, 43609, 43613, 43627, 43633, 43649, 43651, 43661, 478 43669, 43691, 43711, 43717, 43721, 43753, 43759, 43777, 43781, 43783, 479 43787, 43789, 43793, 43801, 43853, 43867, 43889, 43891, 43913, 43933, 480 43943, 43951, 43961, 43963, 43969, 43973, 43987, 43991, 43997, 44017, 481 44021, 44027, 44029, 44041, 44053, 44059, 44071, 44087, 44089, 44101, 482 44111, 44119, 44123, 44129, 44131, 44159, 44171, 44179, 44189, 44201, 483 44203, 44207, 44221, 44249, 44257, 44263, 44267, 44269, 44273, 44279, 484 44281, 44293, 44351, 44357, 44371, 44381, 44383, 44389, 44417, 44449, 485 44453, 44483, 44491, 44497, 44501, 44507, 44519, 44531, 44533, 44537, 486 44543, 44549, 44563, 44579, 44587, 44617, 44621, 44623, 44633, 44641, 487 44647, 44651, 44657, 44683, 44687, 44699, 44701, 44711, 44729, 44741, 488 44753, 44771, 44773, 44777, 44789, 44797, 44809, 44819, 44839, 44843, 489 44851, 44867, 44879, 44887, 44893, 44909, 44917, 44927, 44939, 44953, 490 44959, 44963, 44971, 44983, 44987, 45007, 45013, 45053, 45061, 45077, 491 45083, 45119, 45121, 45127, 45131, 45137, 45139, 45161, 45179, 45181, 492 45191, 45197, 45233, 45247, 45259, 45263, 45281, 45289, 45293, 45307, 493 45317, 45319, 45329, 45337, 45341, 45343, 45361, 45377, 45389, 45403, 494 45413, 45427, 45433, 45439, 45481, 45491, 45497, 45503, 45523, 45533, 495 45541, 45553, 45557, 45569, 45587, 45589, 45599, 45613, 45631, 45641, 496 45659, 45667, 45673, 45677, 45691, 45697, 45707, 45737, 45751, 45757, 497 45763, 45767, 45779, 45817, 45821, 45823, 45827, 45833, 45841, 45853, 498 45863, 45869, 45887, 45893, 45943, 45949, 45953, 45959, 45971, 45979, 499 45989, 46021, 46027, 46049, 46051, 46061, 46073, 46091, 46093, 46099, 500 46103, 46133, 46141, 46147, 46153, 46171, 46181, 46183, 46187, 46199, 501 46219, 46229, 46237, 46261, 46271, 46273, 46279, 46301, 46307, 46309, 502 46327, 46337, 46349, 46351, 46381, 46399, 46411, 46439, 46441, 46447, 503 46451, 46457, 46471, 46477, 46489, 46499, 46507, 46511, 46523, 46549, 504 46559, 46567, 46573, 46589, 46591, 46601, 46619, 46633, 46639, 46643, 505 46649, 46663, 46679, 46681, 46687, 46691, 46703, 46723, 46727, 46747, 506 46751, 46757, 46769, 46771, 46807, 46811, 46817, 46819, 46829, 46831, 507 46853, 46861, 46867, 46877, 46889, 46901, 46919, 46933, 46957, 46993, 508 46997, 47017, 47041, 47051, 47057, 47059, 47087, 47093, 47111, 47119, 509 47123, 47129, 47137, 47143, 47147, 47149, 47161, 47189, 47207, 47221, 510 47237, 47251, 47269, 47279, 47287, 47293, 47297, 47303, 47309, 47317, 511 47339, 47351, 47353, 47363, 47381, 47387, 47389, 47407, 47417, 47419, 512 47431, 47441, 47459, 47491, 47497, 47501, 47507, 47513, 47521, 47527, 513 47533, 47543, 47563, 47569, 47581, 47591, 47599, 47609, 47623, 47629, 514 47639, 47653, 47657, 47659, 47681, 47699, 47701, 47711, 47713, 47717, 515 47737, 47741, 47743, 47777, 47779, 47791, 47797, 47807, 47809, 47819, 516 47837, 47843, 47857, 47869, 47881, 47903, 47911, 47917, 47933, 47939, 517 47947, 47951, 47963, 47969, 47977, 47981, 48017, 48023, 48029, 48049, 518 48073, 48079, 48091, 48109, 48119, 48121, 48131, 48157, 48163, 48179, 519 48187, 48193, 48197, 48221, 48239, 48247, 48259, 48271, 48281, 48299, 520 48311, 48313, 48337, 48341, 48353, 48371, 48383, 48397, 48407, 48409, 521 48413, 48437, 48449, 48463, 48473, 48479, 48481, 48487, 48491, 48497, 522 48523, 48527, 48533, 48539, 48541, 48563, 48571, 48589, 48593, 48611, 523 48619, 48623, 48647, 48649, 48661, 48673, 48677, 48679, 48731, 48733, 524 48751, 48757, 48761, 48767, 48779, 48781, 48787, 48799, 48809, 48817, 525 48821, 48823, 48847, 48857, 48859, 48869, 48871, 48883, 48889, 48907, 526 48947, 48953, 48973, 48989, 48991, 49003, 49009, 49019, 49031, 49033, 527 49037, 49043, 49057, 49069, 49081, 49103, 49109, 49117, 49121, 49123, 528 49139, 49157, 49169, 49171, 49177, 49193, 49199, 49201, 49207, 49211, 529 49223, 49253, 49261, 49277, 49279, 49297, 49307, 49331, 49333, 49339, 530 49363, 49367, 49369, 49391, 49393, 49409, 49411, 49417, 49429, 49433, 531 49451, 49459, 49463, 49477, 49481, 49499, 49523, 49529, 49531, 49537, 532 49547, 49549, 49559, 49597, 49603, 49613, 49627, 49633, 49639, 49663, 533 49667, 49669, 49681, 49697, 49711, 49727, 49739, 49741, 49747, 49757, 534 49783, 49787, 49789, 49801, 49807, 49811, 49823, 49831, 49843, 49853, 535 49871, 49877, 49891, 49919, 49921, 49927, 49937, 49939, 49943, 49957, 536 49991, 49993, 49999, 50021, 50023, 50033, 50047, 50051, 50053, 50069, 537 50077, 50087, 50093, 50101, 50111, 50119, 50123, 50129, 50131, 50147, 538 50153, 50159, 50177, 50207, 50221, 50227, 50231, 50261, 50263, 50273, 539 50287, 50291, 50311, 50321, 50329, 50333, 50341, 50359, 50363, 50377, 540 50383, 50387, 50411, 50417, 50423, 50441, 50459, 50461, 50497, 50503, 541 50513, 50527, 50539, 50543, 50549, 50551, 50581, 50587, 50591, 50593, 542 50599, 50627, 50647, 50651, 50671, 50683, 50707, 50723, 50741, 50753, 543 50767, 50773, 50777, 50789, 50821, 50833, 50839, 50849, 50857, 50867, 544 50873, 50891, 50893, 50909, 50923, 50929, 50951, 50957, 50969, 50971, 545 50989, 50993, 51001, 51031, 51043, 51047, 51059, 51061, 51071, 51109, 546 51131, 51133, 51137, 51151, 51157, 51169, 51193, 51197, 51199, 51203, 547 51217, 51229, 51239, 51241, 51257, 51263, 51283, 51287, 51307, 51329, 548 51341, 51343, 51347, 51349, 51361, 51383, 51407, 51413, 51419, 51421, 549 51427, 51431, 51437, 51439, 51449, 51461, 51473, 51479, 51481, 51487, 550 51503, 51511, 51517, 51521, 51539, 51551, 51563, 51577, 51581, 51593, 551 51599, 51607, 51613, 51631, 51637, 51647, 51659, 51673, 51679, 51683, 552 51691, 51713, 51719, 51721, 51749, 51767, 51769, 51787, 51797, 51803, 553 51817, 51827, 51829, 51839, 51853, 51859, 51869, 51871, 51893, 51899, 554 51907, 51913, 51929, 51941, 51949, 51971, 51973, 51977, 51991, 52009, 555 52021, 52027, 52051, 52057, 52067, 52069, 52081, 52103, 52121, 52127, 556 52147, 52153, 52163, 52177, 52181, 52183, 52189, 52201, 52223, 52237, 557 52249, 52253, 52259, 52267, 52289, 52291, 52301, 52313, 52321, 52361, 558 52363, 52369, 52379, 52387, 52391, 52433, 52453, 52457, 52489, 52501, 559 52511, 52517, 52529, 52541, 52543, 52553, 52561, 52567, 52571, 52579, 560 52583, 52609, 52627, 52631, 52639, 52667, 52673, 52691, 52697, 52709, 561 52711, 52721, 52727, 52733, 52747, 52757, 52769, 52783, 52807, 52813, 562 52817, 52837, 52859, 52861, 52879, 52883, 52889, 52901, 52903, 52919, 563 52937, 52951, 52957, 52963, 52967, 52973, 52981, 52999, 53003, 53017, 564 53047, 53051, 53069, 53077, 53087, 53089, 53093, 53101, 53113, 53117, 565 53129, 53147, 53149, 53161, 53171, 53173, 53189, 53197, 53201, 53231, 566 53233, 53239, 53267, 53269, 53279, 53281, 53299, 53309, 53323, 53327, 567 53353, 53359, 53377, 53381, 53401, 53407, 53411, 53419, 53437, 53441, 568 53453, 53479, 53503, 53507, 53527, 53549, 53551, 53569, 53591, 53593, 569 53597, 53609, 53611, 53617, 53623, 53629, 53633, 53639, 53653, 53657, 570 53681, 53693, 53699, 53717, 53719, 53731, 53759, 53773, 53777, 53783, 571 53791, 53813, 53819, 53831, 53849, 53857, 53861, 53881, 53887, 53891, 572 53897, 53899, 53917, 53923, 53927, 53939, 53951, 53959, 53987, 53993, 573 54001, 54011, 54013, 54037, 54049, 54059, 54083, 54091, 54101, 54121, 574 54133, 54139, 54151, 54163, 54167, 54181, 54193, 54217, 54251, 54269, 575 54277, 54287, 54293, 54311, 54319, 54323, 54331, 54347, 54361, 54367, 576 54371, 54377, 54401, 54403, 54409, 54413, 54419, 54421, 54437, 54443, 577 54449, 54469, 54493, 54497, 54499, 54503, 54517, 54521, 54539, 54541, 578 54547, 54559, 54563, 54577, 54581, 54583, 54601, 54617, 54623, 54629, 579 54631, 54647, 54667, 54673, 54679, 54709, 54713, 54721, 54727, 54751, 580 54767, 54773, 54779, 54787, 54799, 54829, 54833, 54851, 54869, 54877, 581 54881, 54907, 54917, 54919, 54941, 54949, 54959, 54973, 54979, 54983, 582 55001, 55009, 55021, 55049, 55051, 55057, 55061, 55073, 55079, 55103, 583 55109, 55117, 55127, 55147, 55163, 55171, 55201, 55207, 55213, 55217, 584 55219, 55229, 55243, 55249, 55259, 55291, 55313, 55331, 55333, 55337, 585 55339, 55343, 55351, 55373, 55381, 55399, 55411, 55439, 55441, 55457, 586 55469, 55487, 55501, 55511, 55529, 55541, 55547, 55579, 55589, 55603, 587 55609, 55619, 55621, 55631, 55633, 55639, 55661, 55663, 55667, 55673, 588 55681, 55691, 55697, 55711, 55717, 55721, 55733, 55763, 55787, 55793, 589 55799, 55807, 55813, 55817, 55819, 55823, 55829, 55837, 55843, 55849, 590 55871, 55889, 55897, 55901, 55903, 55921, 55927, 55931, 55933, 55949, 591 55967, 55987, 55997, 56003, 56009, 56039, 56041, 56053, 56081, 56087, 592 56093, 56099, 56101, 56113, 56123, 56131, 56149, 56167, 56171, 56179, 593 56197, 56207, 56209, 56237, 56239, 56249, 56263, 56267, 56269, 56299, 594 56311, 56333, 56359, 56369, 56377, 56383, 56393, 56401, 56417, 56431, 595 56437, 56443, 56453, 56467, 56473, 56477, 56479, 56489, 56501, 56503, 596 56509, 56519, 56527, 56531, 56533, 56543, 56569, 56591, 56597, 56599, 597 56611, 56629, 56633, 56659, 56663, 56671, 56681, 56687, 56701, 56711, 598 56713, 56731, 56737, 56747, 56767, 56773, 56779, 56783, 56807, 56809, 599 56813, 56821, 56827, 56843, 56857, 56873, 56891, 56893, 56897, 56909, 600 56911, 56921, 56923, 56929, 56941, 56951, 56957, 56963, 56983, 56989, 601 56993, 56999, 57037, 57041, 57047, 57059, 57073, 57077, 57089, 57097, 602 57107, 57119, 57131, 57139, 57143, 57149, 57163, 57173, 57179, 57191, 603 57193, 57203, 57221, 57223, 57241, 57251, 57259, 57269, 57271, 57283, 604 57287, 57301, 57329, 57331, 57347, 57349, 57367, 57373, 57383, 57389, 605 57397, 57413, 57427, 57457, 57467, 57487, 57493, 57503, 57527, 57529, 606 57557, 57559, 57571, 57587, 57593, 57601, 57637, 57641, 57649, 57653, 607 57667, 57679, 57689, 57697, 57709, 57713, 57719, 57727, 57731, 57737, 608 57751, 57773, 57781, 57787, 57791, 57793, 57803, 57809, 57829, 57839, 609 57847, 57853, 57859, 57881, 57899, 57901, 57917, 57923, 57943, 57947, 610 57973, 57977, 57991, 58013, 58027, 58031, 58043, 58049, 58057, 58061, 611 58067, 58073, 58099, 58109, 58111, 58129, 58147, 58151, 58153, 58169, 612 58171, 58189, 58193, 58199, 58207, 58211, 58217, 58229, 58231, 58237, 613 58243, 58271, 58309, 58313, 58321, 58337, 58363, 58367, 58369, 58379, 614 58391, 58393, 58403, 58411, 58417, 58427, 58439, 58441, 58451, 58453, 615 58477, 58481, 58511, 58537, 58543, 58549, 58567, 58573, 58579, 58601, 616 58603, 58613, 58631, 58657, 58661, 58679, 58687, 58693, 58699, 58711, 617 58727, 58733, 58741, 58757, 58763, 58771, 58787, 58789, 58831, 58889, 618 58897, 58901, 58907, 58909, 58913, 58921, 58937, 58943, 58963, 58967, 619 58979, 58991, 58997, 59009, 59011, 59021, 59023, 59029, 59051, 59053, 620 59063, 59069, 59077, 59083, 59093, 59107, 59113, 59119, 59123, 59141, 621 59149, 59159, 59167, 59183, 59197, 59207, 59209, 59219, 59221, 59233, 622 59239, 59243, 59263, 59273, 59281, 59333, 59341, 59351, 59357, 59359, 623 59369, 59377, 59387, 59393, 59399, 59407, 59417, 59419, 59441, 59443, 624 59447, 59453, 59467, 59471, 59473, 59497, 59509, 59513, 59539, 59557, 625 59561, 59567, 59581, 59611, 59617, 59621, 59627, 59629, 59651, 59659, 626 59663, 59669, 59671, 59693, 59699, 59707, 59723, 59729, 59743, 59747, 627 59753, 59771, 59779, 59791, 59797, 59809, 59833, 59863, 59879, 59887, 628 59921, 59929, 59951, 59957, 59971, 59981, 59999, 60013, 60017, 60029, 629 60037, 60041, 60077, 60083, 60089, 60091, 60101, 60103, 60107, 60127, 630 60133, 60139, 60149, 60161, 60167, 60169, 60209, 60217, 60223, 60251, 631 60257, 60259, 60271, 60289, 60293, 60317, 60331, 60337, 60343, 60353, 632 60373, 60383, 60397, 60413, 60427, 60443, 60449, 60457, 60493, 60497, 633 60509, 60521, 60527, 60539, 60589, 60601, 60607, 60611, 60617, 60623, 634 60631, 60637, 60647, 60649, 60659, 60661, 60679, 60689, 60703, 60719, 635 60727, 60733, 60737, 60757, 60761, 60763, 60773, 60779, 60793, 60811, 636 60821, 60859, 60869, 60887, 60889, 60899, 60901, 60913, 60917, 60919, 637 60923, 60937, 60943, 60953, 60961, 61001, 61007, 61027, 61031, 61043, 638 61051, 61057, 61091, 61099, 61121, 61129, 61141, 61151, 61153, 61169, 639 61211, 61223, 61231, 61253, 61261, 61283, 61291, 61297, 61331, 61333, 640 61339, 61343, 61357, 61363, 61379, 61381, 61403, 61409, 61417, 61441, 641 61463, 61469, 61471, 61483, 61487, 61493, 61507, 61511, 61519, 61543, 642 61547, 61553, 61559, 61561, 61583, 61603, 61609, 61613, 61627, 61631, 643 61637, 61643, 61651, 61657, 61667, 61673, 61681, 61687, 61703, 61717, 644 61723, 61729, 61751, 61757, 61781, 61813, 61819, 61837, 61843, 61861, 645 61871, 61879, 61909, 61927, 61933, 61949, 61961, 61967, 61979, 61981, 646 61987, 61991, 62003, 62011, 62017, 62039, 62047, 62053, 62057, 62071, 647 62081, 62099, 62119, 62129, 62131, 62137, 62141, 62143, 62171, 62189, 648 62191, 62201, 62207, 62213, 62219, 62233, 62273, 62297, 62299, 62303, 649 62311, 62323, 62327, 62347, 62351, 62383, 62401, 62417, 62423, 62459, 650 62467, 62473, 62477, 62483, 62497, 62501, 62507, 62533, 62539, 62549, 651 62563, 62581, 62591, 62597, 62603, 62617, 62627, 62633, 62639, 62653, 652 62659, 62683, 62687, 62701, 62723, 62731, 62743, 62753, 62761, 62773, 653 62791, 62801, 62819, 62827, 62851, 62861, 62869, 62873, 62897, 62903, 654 62921, 62927, 62929, 62939, 62969, 62971, 62981, 62983, 62987, 62989, 655 63029, 63031, 63059, 63067, 63073, 63079, 63097, 63103, 63113, 63127, 656 63131, 63149, 63179, 63197, 63199, 63211, 63241, 63247, 63277, 63281, 657 63299, 63311, 63313, 63317, 63331, 63337, 63347, 63353, 63361, 63367, 658 63377, 63389, 63391, 63397, 63409, 63419, 63421, 63439, 63443, 63463, 659 63467, 63473, 63487, 63493, 63499, 63521, 63527, 63533, 63541, 63559, 660 63577, 63587, 63589, 63599, 63601, 63607, 63611, 63617, 63629, 63647, 661 63649, 63659, 63667, 63671, 63689, 63691, 63697, 63703, 63709, 63719, 662 63727, 63737, 63743, 63761, 63773, 63781, 63793, 63799, 63803, 63809, 663 63823, 63839, 63841, 63853, 63857, 63863, 63901, 63907, 63913, 63929, 664 63949, 63977, 63997, 64007, 64013, 64019, 64033, 64037, 64063, 64067, 665 64081, 64091, 64109, 64123, 64151, 64153, 64157, 64171, 64187, 64189, 666 64217, 64223, 64231, 64237, 64271, 64279, 64283, 64301, 64303, 64319, 667 64327, 64333, 64373, 64381, 64399, 64403, 64433, 64439, 64451, 64453, 668 64483, 64489, 64499, 64513, 64553, 64567, 64577, 64579, 64591, 64601, 669 64609, 64613, 64621, 64627, 64633, 64661, 64663, 64667, 64679, 64693, 670 64709, 64717, 64747, 64763, 64781, 64783, 64793, 64811, 64817, 64849, 671 64853, 64871, 64877, 64879, 64891, 64901, 64919, 64921, 64927, 64937, 672 64951, 64969, 64997, 65003, 65011, 65027, 65029, 65033, 65053, 65063, 673 65071, 65089, 65099, 65101, 65111, 65119, 65123, 65129, 65141, 65147, 674 65167, 65171, 65173, 65179, 65183, 65203, 65213, 65239, 65257, 65267, 675 65269, 65287, 65293, 65309, 65323, 65327, 65353, 65357, 65371, 65381, 676 65393, 65407, 65413, 65419, 65423, 65437, 65447, 65449, 65479, 65497, 677 65519, 65521, 65537, 65539, 65543, 65551, 65557, 65563, 65579, 65581, 678 65587, 65599, 65609, 65617, 65629, 65633, 65647, 65651, 65657, 65677, 679 65687, 65699, 65701, 65707, 65713, 65717, 65719, 65729, 65731, 65761, 680 65777, 65789, 65809, 65827, 65831, 65837, 65839, 65843, 65851, 65867, 681 65881, 65899, 65921, 65927, 65929, 65951, 65957, 65963, 65981, 65983, 682 65993, 66029, 66037, 66041, 66047, 66067, 66071, 66083, 66089, 66103, 683 66107, 66109, 66137, 66161, 66169, 66173, 66179, 66191, 66221, 66239, 684 66271, 66293, 66301, 66337, 66343, 66347, 66359, 66361, 66373, 66377, 685 66383, 66403, 66413, 66431, 66449, 66457, 66463, 66467, 66491, 66499, 686 66509, 66523, 66529, 66533, 66541, 66553, 66569, 66571, 66587, 66593, 687 66601, 66617, 66629, 66643, 66653, 66683, 66697, 66701, 66713, 66721, 688 66733, 66739, 66749, 66751, 66763, 66791, 66797, 66809, 66821, 66841, 689 66851, 66853, 66863, 66877, 66883, 66889, 66919, 66923, 66931, 66943, 690 66947, 66949, 66959, 66973, 66977, 67003, 67021, 67033, 67043, 67049, 691 67057, 67061, 67073, 67079, 67103, 67121, 67129, 67139, 67141, 67153, 692 67157, 67169, 67181, 67187, 67189, 67211, 67213, 67217, 67219, 67231, 693 67247, 67261, 67271, 67273, 67289, 67307, 67339, 67343, 67349, 67369, 694 67391, 67399, 67409, 67411, 67421, 67427, 67429, 67433, 67447, 67453, 695 67477, 67481, 67489, 67493, 67499, 67511, 67523, 67531, 67537, 67547, 696 67559, 67567, 67577, 67579, 67589, 67601, 67607, 67619, 67631, 67651, 697 67679, 67699, 67709, 67723, 67733, 67741, 67751, 67757, 67759, 67763, 698 67777, 67783, 67789, 67801, 67807, 67819, 67829, 67843, 67853, 67867, 699 67883, 67891, 67901, 67927, 67931, 67933, 67939, 67943, 67957, 67961, 700 67967, 67979, 67987, 67993, 68023, 68041, 68053, 68059, 68071, 68087, 701 68099, 68111, 68113, 68141, 68147, 68161, 68171, 68207, 68209, 68213, 702 68219, 68227, 68239, 68261, 68279, 68281, 68311, 68329, 68351, 68371, 703 68389, 68399, 68437, 68443, 68447, 68449, 68473, 68477, 68483, 68489, 704 68491, 68501, 68507, 68521, 68531, 68539, 68543, 68567, 68581, 68597, 705 68611, 68633, 68639, 68659, 68669, 68683, 68687, 68699, 68711, 68713, 706 68729, 68737, 68743, 68749, 68767, 68771, 68777, 68791, 68813, 68819, 707 68821, 68863, 68879, 68881, 68891, 68897, 68899, 68903, 68909, 68917, 708 68927, 68947, 68963, 68993, 69001, 69011, 69019, 69029, 69031, 69061, 709 69067, 69073, 69109, 69119, 69127, 69143, 69149, 69151, 69163, 69191, 710 69193, 69197, 69203, 69221, 69233, 69239, 69247, 69257, 69259, 69263, 711 69313, 69317, 69337, 69341, 69371, 69379, 69383, 69389, 69401, 69403, 712 69427, 69431, 69439, 69457, 69463, 69467, 69473, 69481, 69491, 69493, 713 69497, 69499, 69539, 69557, 69593, 69623, 69653, 69661, 69677, 69691, 714 69697, 69709, 69737, 69739, 69761, 69763, 69767, 69779, 69809, 69821, 715 69827, 69829, 69833, 69847, 69857, 69859, 69877, 69899, 69911, 69929, 716 69931, 69941, 69959, 69991, 69997, 70001, 70003, 70009, 70019, 70039, 717 70051, 70061, 70067, 70079, 70099, 70111, 70117, 70121, 70123, 70139, 718 70141, 70157, 70163, 70177, 70181, 70183, 70199, 70201, 70207, 70223, 719 70229, 70237, 70241, 70249, 70271, 70289, 70297, 70309, 70313, 70321, 720 70327, 70351, 70373, 70379, 70381, 70393, 70423, 70429, 70439, 70451, 721 70457, 70459, 70481, 70487, 70489, 70501, 70507, 70529, 70537, 70549, 722 70571, 70573, 70583, 70589, 70607, 70619, 70621, 70627, 70639, 70657, 723 70663, 70667, 70687, 70709, 70717, 70729, 70753, 70769, 70783, 70793, 724 70823, 70841, 70843, 70849, 70853, 70867, 70877, 70879, 70891, 70901, 725 70913, 70919, 70921, 70937, 70949, 70951, 70957, 70969, 70979, 70981, 726 70991, 70997, 70999, 71011, 71023, 71039, 71059, 71069, 71081, 71089, 727 71119, 71129, 71143, 71147, 71153, 71161, 71167, 71171, 71191, 71209, 728 71233, 71237, 71249, 71257, 71261, 71263, 71287, 71293, 71317, 71327, 729 71329, 71333, 71339, 71341, 71347, 71353, 71359, 71363, 71387, 71389, 730 71399, 71411, 71413, 71419, 71429, 71437, 71443, 71453, 71471, 71473, 731 71479, 71483, 71503, 71527, 71537, 71549, 71551, 71563, 71569, 71593, 732 71597, 71633, 71647, 71663, 71671, 71693, 71699, 71707, 71711, 71713, 733 71719, 71741, 71761, 71777, 71789, 71807, 71809, 71821, 71837, 71843, 734 71849, 71861, 71867, 71879, 71881, 71887, 71899, 71909, 71917, 71933, 735 71941, 71947, 71963, 71971, 71983, 71987, 71993, 71999, 72019, 72031, 736 72043, 72047, 72053, 72073, 72077, 72089, 72091, 72101, 72103, 72109, 737 72139, 72161, 72167, 72169, 72173, 72211, 72221, 72223, 72227, 72229, 738 72251, 72253, 72269, 72271, 72277, 72287, 72307, 72313, 72337, 72341, 739 72353, 72367, 72379, 72383, 72421, 72431, 72461, 72467, 72469, 72481, 740 72493, 72497, 72503, 72533, 72547, 72551, 72559, 72577, 72613, 72617, 741 72623, 72643, 72647, 72649, 72661, 72671, 72673, 72679, 72689, 72701, 742 72707, 72719, 72727, 72733, 72739, 72763, 72767, 72797, 72817, 72823, 743 72859, 72869, 72871, 72883, 72889, 72893, 72901, 72907, 72911, 72923, 744 72931, 72937, 72949, 72953, 72959, 72973, 72977, 72997, 73009, 73013, 745 73019, 73037, 73039, 73043, 73061, 73063, 73079, 73091, 73121, 73127, 746 73133, 73141, 73181, 73189, 73237, 73243, 73259, 73277, 73291, 73303, 747 73309, 73327, 73331, 73351, 73361, 73363, 73369, 73379, 73387, 73417, 748 73421, 73433, 73453, 73459, 73471, 73477, 73483, 73517, 73523, 73529, 749 73547, 73553, 73561, 73571, 73583, 73589, 73597, 73607, 73609, 73613, 750 73637, 73643, 73651, 73673, 73679, 73681, 73693, 73699, 73709, 73721, 751 73727, 73751, 73757, 73771, 73783, 73819, 73823, 73847, 73849, 73859, 752 73867, 73877, 73883, 73897, 73907, 73939, 73943, 73951, 73961, 73973, 753 73999, 74017, 74021, 74027, 74047, 74051, 74071, 74077, 74093, 74099, 754 74101, 74131, 74143, 74149, 74159, 74161, 74167, 74177, 74189, 74197, 755 74201, 74203, 74209, 74219, 74231, 74257, 74279, 74287, 74293, 74297, 756 74311, 74317, 74323, 74353, 74357, 74363, 74377, 74381, 74383, 74411, 757 74413, 74419, 74441, 74449, 74453, 74471, 74489, 74507, 74509, 74521, 758 74527, 74531, 74551, 74561, 74567, 74573, 74587, 74597, 74609, 74611, 759 74623, 74653, 74687, 74699, 74707, 74713, 74717, 74719, 74729, 74731, 760 74747, 74759, 74761, 74771, 74779, 74797, 74821, 74827, 74831, 74843, 761 74857, 74861, 74869, 74873, 74887, 74891, 74897, 74903, 74923, 74929, 762 74933, 74941, 74959, 75011, 75013, 75017, 75029, 75037, 75041, 75079, 763 75083, 75109, 75133, 75149, 75161, 75167, 75169, 75181, 75193, 75209, 764 75211, 75217, 75223, 75227, 75239, 75253, 75269, 75277, 75289, 75307, 765 75323, 75329, 75337, 75347, 75353, 75367, 75377, 75389, 75391, 75401, 766 75403, 75407, 75431, 75437, 75479, 75503, 75511, 75521, 75527, 75533, 767 75539, 75541, 75553, 75557, 75571, 75577, 75583, 75611, 75617, 75619, 768 75629, 75641, 75653, 75659, 75679, 75683, 75689, 75703, 75707, 75709, 769 75721, 75731, 75743, 75767, 75773, 75781, 75787, 75793, 75797, 75821, 770 75833, 75853, 75869, 75883, 75913, 75931, 75937, 75941, 75967, 75979, 771 75983, 75989, 75991, 75997, 76001, 76003, 76031, 76039, 76079, 76081, 772 76091, 76099, 76103, 76123, 76129, 76147, 76157, 76159, 76163, 76207, 773 76213, 76231, 76243, 76249, 76253, 76259, 76261, 76283, 76289, 76303, 774 76333, 76343, 76367, 76369, 76379, 76387, 76403, 76421, 76423, 76441, 775 76463, 76471, 76481, 76487, 76493, 76507, 76511, 76519, 76537, 76541, 776 76543, 76561, 76579, 76597, 76603, 76607, 76631, 76649, 76651, 76667, 777 76673, 76679, 76697, 76717, 76733, 76753, 76757, 76771, 76777, 76781, 778 76801, 76819, 76829, 76831, 76837, 76847, 76871, 76873, 76883, 76907, 779 76913, 76919, 76943, 76949, 76961, 76963, 76991, 77003, 77017, 77023, 780 77029, 77041, 77047, 77069, 77081, 77093, 77101, 77137, 77141, 77153, 781 77167, 77171, 77191, 77201, 77213, 77237, 77239, 77243, 77249, 77261, 782 77263, 77267, 77269, 77279, 77291, 77317, 77323, 77339, 77347, 77351, 783 77359, 77369, 77377, 77383, 77417, 77419, 77431, 77447, 77471, 77477, 784 77479, 77489, 77491, 77509, 77513, 77521, 77527, 77543, 77549, 77551, 785 77557, 77563, 77569, 77573, 77587, 77591, 77611, 77617, 77621, 77641, 786 77647, 77659, 77681, 77687, 77689, 77699, 77711, 77713, 77719, 77723, 787 77731, 77743, 77747, 77761, 77773, 77783, 77797, 77801, 77813, 77839, 788 77849, 77863, 77867, 77893, 77899, 77929, 77933, 77951, 77969, 77977, 789 77983, 77999, 78007, 78017, 78031, 78041, 78049, 78059, 78079, 78101, 790 78121, 78137, 78139, 78157, 78163, 78167, 78173, 78179, 78191, 78193, 791 78203, 78229, 78233, 78241, 78259, 78277, 78283, 78301, 78307, 78311, 792 78317, 78341, 78347, 78367, 78401, 78427, 78437, 78439, 78467, 78479, 793 78487, 78497, 78509, 78511, 78517, 78539, 78541, 78553, 78569, 78571, 794 78577, 78583, 78593, 78607, 78623, 78643, 78649, 78653, 78691, 78697, 795 78707, 78713, 78721, 78737, 78779, 78781, 78787, 78791, 78797, 78803, 796 78809, 78823, 78839, 78853, 78857, 78877, 78887, 78889, 78893, 78901, 797 78919, 78929, 78941, 78977, 78979, 78989, 79031, 79039, 79043, 79063, 798 79087, 79103, 79111, 79133, 79139, 79147, 79151, 79153, 79159, 79181, 799 79187, 79193, 79201, 79229, 79231, 79241, 79259, 79273, 79279, 79283, 800 79301, 79309, 79319, 79333, 79337, 79349, 79357, 79367, 79379, 79393, 801 79397, 79399, 79411, 79423, 79427, 79433, 79451, 79481, 79493, 79531, 802 79537, 79549, 79559, 79561, 79579, 79589, 79601, 79609, 79613, 79621, 803 79627, 79631, 79633, 79657, 79669, 79687, 79691, 79693, 79697, 79699, 804 79757, 79769, 79777, 79801, 79811, 79813, 79817, 79823, 79829, 79841, 805 79843, 79847, 79861, 79867, 79873, 79889, 79901, 79903, 79907, 79939, 806 79943, 79967, 79973, 79979, 79987, 79997, 79999, 80021, 80039, 80051, 807 80071, 80077, 80107, 80111, 80141, 80147, 80149, 80153, 80167, 80173, 808 80177, 80191, 80207, 80209, 80221, 80231, 80233, 80239, 80251, 80263, 809 80273, 80279, 80287, 80309, 80317, 80329, 80341, 80347, 80363, 80369, 810 80387, 80407, 80429, 80447, 80449, 80471, 80473, 80489, 80491, 80513, 811 80527, 80537, 80557, 80567, 80599, 80603, 80611, 80621, 80627, 80629, 812 80651, 80657, 80669, 80671, 80677, 80681, 80683, 80687, 80701, 80713, 813 80737, 80747, 80749, 80761, 80777, 80779, 80783, 80789, 80803, 80809, 814 80819, 80831, 80833, 80849, 80863, 80897, 80909, 80911, 80917, 80923, 815 80929, 80933, 80953, 80963, 80989, 81001, 81013, 81017, 81019, 81023, 816 81031, 81041, 81043, 81047, 81049, 81071, 81077, 81083, 81097, 81101, 817 81119, 81131, 81157, 81163, 81173, 81181, 81197, 81199, 81203, 81223, 818 81233, 81239, 81281, 81283, 81293, 81299, 81307, 81331, 81343, 81349, 819 81353, 81359, 81371, 81373, 81401, 81409, 81421, 81439, 81457, 81463, 820 81509, 81517, 81527, 81533, 81547, 81551, 81553, 81559, 81563, 81569, 821 81611, 81619, 81629, 81637, 81647, 81649, 81667, 81671, 81677, 81689, 822 81701, 81703, 81707, 81727, 81737, 81749, 81761, 81769, 81773, 81799, 823 81817, 81839, 81847, 81853, 81869, 81883, 81899, 81901, 81919, 81929, 824 81931, 81937, 81943, 81953, 81967, 81971, 81973, 82003, 82007, 82009, 825 82013, 82021, 82031, 82037, 82039, 82051, 82067, 82073, 82129, 82139, 826 82141, 82153, 82163, 82171, 82183, 82189, 82193, 82207, 82217, 82219, 827 82223, 82231, 82237, 82241, 82261, 82267, 82279, 82301, 82307, 82339, 828 82349, 82351, 82361, 82373, 82387, 82393, 82421, 82457, 82463, 82469, 829 82471, 82483, 82487, 82493, 82499, 82507, 82529, 82531, 82549, 82559, 830 82561, 82567, 82571, 82591, 82601, 82609, 82613, 82619, 82633, 82651, 831 82657, 82699, 82721, 82723, 82727, 82729, 82757, 82759, 82763, 82781, 832 82787, 82793, 82799, 82811, 82813, 82837, 82847, 82883, 82889, 82891, 833 82903, 82913, 82939, 82963, 82981, 82997, 83003, 83009, 83023, 83047, 834 83059, 83063, 83071, 83077, 83089, 83093, 83101, 83117, 83137, 83177, 835 83203, 83207, 83219, 83221, 83227, 83231, 83233, 83243, 83257, 83267, 836 83269, 83273, 83299, 83311, 83339, 83341, 83357, 83383, 83389, 83399, 837 83401, 83407, 83417, 83423, 83431, 83437, 83443, 83449, 83459, 83471, 838 83477, 83497, 83537, 83557, 83561, 83563, 83579, 83591, 83597, 83609, 839 83617, 83621, 83639, 83641, 83653, 83663, 83689, 83701, 83717, 83719, 840 83737, 83761, 83773, 83777, 83791, 83813, 83833, 83843, 83857, 83869, 841 83873, 83891, 83903, 83911, 83921, 83933, 83939, 83969, 83983, 83987, 842 84011, 84017, 84047, 84053, 84059, 84061, 84067, 84089, 84121, 84127, 843 84131, 84137, 84143, 84163, 84179, 84181, 84191, 84199, 84211, 84221, 844 84223, 84229, 84239, 84247, 84263, 84299, 84307, 84313, 84317, 84319, 845 84347, 84349, 84377, 84389, 84391, 84401, 84407, 84421, 84431, 84437, 846 84443, 84449, 84457, 84463, 84467, 84481, 84499, 84503, 84509, 84521, 847 84523, 84533, 84551, 84559, 84589, 84629, 84631, 84649, 84653, 84659, 848 84673, 84691, 84697, 84701, 84713, 84719, 84731, 84737, 84751, 84761, 849 84787, 84793, 84809, 84811, 84827, 84857, 84859, 84869, 84871, 84913, 850 84919, 84947, 84961, 84967, 84977, 84979, 84991, 85009, 85021, 85027, 851 85037, 85049, 85061, 85081, 85087, 85091, 85093, 85103, 85109, 85121, 852 85133, 85147, 85159, 85193, 85199, 85201, 85213, 85223, 85229, 85237, 853 85243, 85247, 85259, 85297, 85303, 85313, 85331, 85333, 85361, 85363, 854 85369, 85381, 85411, 85427, 85429, 85439, 85447, 85451, 85453, 85469, 855 85487, 85513, 85517, 85523, 85531, 85549, 85571, 85577, 85597, 85601, 856 85607, 85619, 85621, 85627, 85639, 85643, 85661, 85667, 85669, 85691, 857 85703, 85711, 85717, 85733, 85751, 85781, 85793, 85817, 85819, 85829, 858 85831, 85837, 85843, 85847, 85853, 85889, 85903, 85909, 85931, 85933, 859 85991, 85999, 86011, 86017, 86027, 86029, 86069, 86077, 86083, 86111, 860 86113, 86117, 86131, 86137, 86143, 86161, 86171, 86179, 86183, 86197, 861 86201, 86209, 86239, 86243, 86249, 86257, 86263, 86269, 86287, 86291, 862 86293, 86297, 86311, 86323, 86341, 86351, 86353, 86357, 86369, 86371, 863 86381, 86389, 86399, 86413, 86423, 86441, 86453, 86461, 86467, 86477, 864 86491, 86501, 86509, 86531, 86533, 86539, 86561, 86573, 86579, 86587, 865 86599, 86627, 86629, 86677, 86689, 86693, 86711, 86719, 86729, 86743, 866 86753, 86767, 86771, 86783, 86813, 86837, 86843, 86851, 86857, 86861, 867 86869, 86923, 86927, 86929, 86939, 86951, 86959, 86969, 86981, 86993, 868 87011, 87013, 87037, 87041, 87049, 87071, 87083, 87103, 87107, 87119, 869 87121, 87133, 87149, 87151, 87179, 87181, 87187, 87211, 87221, 87223, 870 87251, 87253, 87257, 87277, 87281, 87293, 87299, 87313, 87317, 87323, 871 87337, 87359, 87383, 87403, 87407, 87421, 87427, 87433, 87443, 87473, 872 87481, 87491, 87509, 87511, 87517, 87523, 87539, 87541, 87547, 87553, 873 87557, 87559, 87583, 87587, 87589, 87613, 87623, 87629, 87631, 87641, 874 87643, 87649, 87671, 87679, 87683, 87691, 87697, 87701, 87719, 87721, 875 87739, 87743, 87751, 87767, 87793, 87797, 87803, 87811, 87833, 87853, 876 87869, 87877, 87881, 87887, 87911, 87917, 87931, 87943, 87959, 87961, 877 87973, 87977, 87991, 88001, 88003, 88007, 88019, 88037, 88069, 88079, 878 88093, 88117, 88129, 88169, 88177, 88211, 88223, 88237, 88241, 88259, 879 88261, 88289, 88301, 88321, 88327, 88337, 88339, 88379, 88397, 88411, 880 88423, 88427, 88463, 88469, 88471, 88493, 88499, 88513, 88523, 88547, 881 88589, 88591, 88607, 88609, 88643, 88651, 88657, 88661, 88663, 88667, 882 88681, 88721, 88729, 88741, 88747, 88771, 88789, 88793, 88799, 88801, 883 88807, 88811, 88813, 88817, 88819, 88843, 88853, 88861, 88867, 88873, 884 88883, 88897, 88903, 88919, 88937, 88951, 88969, 88993, 88997, 89003, 885 89009, 89017, 89021, 89041, 89051, 89057, 89069, 89071, 89083, 89087, 886 89101, 89107, 89113, 89119, 89123, 89137, 89153, 89189, 89203, 89209, 887 89213, 89227, 89231, 89237, 89261, 89269, 89273, 89293, 89303, 89317, 888 89329, 89363, 89371, 89381, 89387, 89393, 89399, 89413, 89417, 89431, 889 89443, 89449, 89459, 89477, 89491, 89501, 89513, 89519, 89521, 89527, 890 89533, 89561, 89563, 89567, 89591, 89597, 89599, 89603, 89611, 89627, 891 89633, 89653, 89657, 89659, 89669, 89671, 89681, 89689, 89753, 89759, 892 89767, 89779, 89783, 89797, 89809, 89819, 89821, 89833, 89839, 89849, 893 89867, 89891, 89897, 89899, 89909, 89917, 89923, 89939, 89959, 89963, 894 89977, 89983, 89989, 90001, 90007, 90011, 90017, 90019, 90023, 90031, 895 90053, 90059, 90067, 90071, 90073, 90089, 90107, 90121, 90127, 90149, 896 90163, 90173, 90187, 90191, 90197, 90199, 90203, 90217, 90227, 90239, 897 90247, 90263, 90271, 90281, 90289, 90313, 90353, 90359, 90371, 90373, 898 90379, 90397, 90401, 90403, 90407, 90437, 90439, 90469, 90473, 90481, 899 90499, 90511, 90523, 90527, 90529, 90533, 90547, 90583, 90599, 90617, 900 90619, 90631, 90641, 90647, 90659, 90677, 90679, 90697, 90703, 90709, 901 90731, 90749, 90787, 90793, 90803, 90821, 90823, 90833, 90841, 90847, 902 90863, 90887, 90901, 90907, 90911, 90917, 90931, 90947, 90971, 90977, 903 90989, 90997, 91009, 91019, 91033, 91079, 91081, 91097, 91099, 91121, 904 91127, 91129, 91139, 91141, 91151, 91153, 91159, 91163, 91183, 91193, 905 91199, 91229, 91237, 91243, 91249, 91253, 91283, 91291, 91297, 91303, 906 91309, 91331, 91367, 91369, 91373, 91381, 91387, 91393, 91397, 91411, 907 91423, 91433, 91453, 91457, 91459, 91463, 91493, 91499, 91513, 91529, 908 91541, 91571, 91573, 91577, 91583, 91591, 91621, 91631, 91639, 91673, 909 91691, 91703, 91711, 91733, 91753, 91757, 91771, 91781, 91801, 91807, 910 91811, 91813, 91823, 91837, 91841, 91867, 91873, 91909, 91921, 91939, 911 91943, 91951, 91957, 91961, 91967, 91969, 91997, 92003, 92009, 92033, 912 92041, 92051, 92077, 92083, 92107, 92111, 92119, 92143, 92153, 92173, 913 92177, 92179, 92189, 92203, 92219, 92221, 92227, 92233, 92237, 92243, 914 92251, 92269, 92297, 92311, 92317, 92333, 92347, 92353, 92357, 92363, 915 92369, 92377, 92381, 92383, 92387, 92399, 92401, 92413, 92419, 92431, 916 92459, 92461, 92467, 92479, 92489, 92503, 92507, 92551, 92557, 92567, 917 92569, 92581, 92593, 92623, 92627, 92639, 92641, 92647, 92657, 92669, 918 92671, 92681, 92683, 92693, 92699, 92707, 92717, 92723, 92737, 92753, 919 92761, 92767, 92779, 92789, 92791, 92801, 92809, 92821, 92831, 92849, 920 92857, 92861, 92863, 92867, 92893, 92899, 92921, 92927, 92941, 92951, 921 92957, 92959, 92987, 92993, 93001, 93047, 93053, 93059, 93077, 93083, 922 93089, 93097, 93103, 93113, 93131, 93133, 93139, 93151, 93169, 93179, 923 93187, 93199, 93229, 93239, 93241, 93251, 93253, 93257, 93263, 93281, 924 93283, 93287, 93307, 93319, 93323, 93329, 93337, 93371, 93377, 93383, 925 93407, 93419, 93427, 93463, 93479, 93481, 93487, 93491, 93493, 93497, 926 93503, 93523, 93529, 93553, 93557, 93559, 93563, 93581, 93601, 93607, 927 93629, 93637, 93683, 93701, 93703, 93719, 93739, 93761, 93763, 93787, 928 93809, 93811, 93827, 93851, 93871, 93887, 93889, 93893, 93901, 93911, 929 93913, 93923, 93937, 93941, 93949, 93967, 93971, 93979, 93983, 93997, 930 94007, 94009, 94033, 94049, 94057, 94063, 94079, 94099, 94109, 94111, 931 94117, 94121, 94151, 94153, 94169, 94201, 94207, 94219, 94229, 94253, 932 94261, 94273, 94291, 94307, 94309, 94321, 94327, 94331, 94343, 94349, 933 94351, 94379, 94397, 94399, 94421, 94427, 94433, 94439, 94441, 94447, 934 94463, 94477, 94483, 94513, 94529, 94531, 94541, 94543, 94547, 94559, 935 94561, 94573, 94583, 94597, 94603, 94613, 94621, 94649, 94651, 94687, 936 94693, 94709, 94723, 94727, 94747, 94771, 94777, 94781, 94789, 94793, 937 94811, 94819, 94823, 94837, 94841, 94847, 94849, 94873, 94889, 94903, 938 94907, 94933, 94949, 94951, 94961, 94993, 94999, 95003, 95009, 95021, 939 95027, 95063, 95071, 95083, 95087, 95089, 95093, 95101, 95107, 95111, 940 95131, 95143, 95153, 95177, 95189, 95191, 95203, 95213, 95219, 95231, 941 95233, 95239, 95257, 95261, 95267, 95273, 95279, 95287, 95311, 95317, 942 95327, 95339, 95369, 95383, 95393, 95401, 95413, 95419, 95429, 95441, 943 95443, 95461, 95467, 95471, 95479, 95483, 95507, 95527, 95531, 95539, 944 95549, 95561, 95569, 95581, 95597, 95603, 95617, 95621, 95629, 95633, 945 95651, 95701, 95707, 95713, 95717, 95723, 95731, 95737, 95747, 95773, 946 95783, 95789, 95791, 95801, 95803, 95813, 95819, 95857, 95869, 95873, 947 95881, 95891, 95911, 95917, 95923, 95929, 95947, 95957, 95959, 95971, 948 95987, 95989, 96001, 96013, 96017, 96043, 96053, 96059, 96079, 96097, 949 96137, 96149, 96157, 96167, 96179, 96181, 96199, 96211, 96221, 96223, 950 96233, 96259, 96263, 96269, 96281, 96289, 96293, 96323, 96329, 96331, 951 96337, 96353, 96377, 96401, 96419, 96431, 96443, 96451, 96457, 96461, 952 96469, 96479, 96487, 96493, 96497, 96517, 96527, 96553, 96557, 96581, 953 96587, 96589, 96601, 96643, 96661, 96667, 96671, 96697, 96703, 96731, 954 96737, 96739, 96749, 96757, 96763, 96769, 96779, 96787, 96797, 96799, 955 96821, 96823, 96827, 96847, 96851, 96857, 96893, 96907, 96911, 96931, 956 96953, 96959, 96973, 96979, 96989, 96997, 97001, 97003, 97007, 97021, 957 97039, 97073, 97081, 97103, 97117, 97127, 97151, 97157, 97159, 97169, 958 97171, 97177, 97187, 97213, 97231, 97241, 97259, 97283, 97301, 97303, 959 97327, 97367, 97369, 97373, 97379, 97381, 97387, 97397, 97423, 97429, 960 97441, 97453, 97459, 97463, 97499, 97501, 97511, 97523, 97547, 97549, 961 97553, 97561, 97571, 97577, 97579, 97583, 97607, 97609, 97613, 97649, 962 97651, 97673, 97687, 97711, 97729, 97771, 97777, 97787, 97789, 97813, 963 97829, 97841, 97843, 97847, 97849, 97859, 97861, 97871, 97879, 97883, 964 97919, 97927, 97931, 97943, 97961, 97967, 97973, 97987, 98009, 98011, 965 98017, 98041, 98047, 98057, 98081, 98101, 98123, 98129, 98143, 98179, 966 98207, 98213, 98221, 98227, 98251, 98257, 98269, 98297, 98299, 98317, 967 98321, 98323, 98327, 98347, 98369, 98377, 98387, 98389, 98407, 98411, 968 98419, 98429, 98443, 98453, 98459, 98467, 98473, 98479, 98491, 98507, 969 98519, 98533, 98543, 98561, 98563, 98573, 98597, 98621, 98627, 98639, 970 98641, 98663, 98669, 98689, 98711, 98713, 98717, 98729, 98731, 98737, 971 98773, 98779, 98801, 98807, 98809, 98837, 98849, 98867, 98869, 98873, 972 98887, 98893, 98897, 98899, 98909, 98911, 98927, 98929, 98939, 98947, 973 98953, 98963, 98981, 98993, 98999, 99013, 99017, 99023, 99041, 99053, 974 99079, 99083, 99089, 99103, 99109, 99119, 99131, 99133, 99137, 99139, 975 99149, 99173, 99181, 99191, 99223, 99233, 99241, 99251, 99257, 99259, 976 99277, 99289, 99317, 99347, 99349, 99367, 99371, 99377, 99391, 99397, 977 99401, 99409, 99431, 99439, 99469, 99487, 99497, 99523, 99527, 99529, 978 99551, 99559, 99563, 99571, 99577, 99581, 99607, 99611, 99623, 99643, 979 99661, 99667, 99679, 99689, 99707, 99709, 99713, 99719, 99721, 99733, 980 99761, 99767, 99787, 99793, 99809, 99817, 99823, 99829, 99833, 99839, 981 99859, 99871, 99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, 982 99989, 99991, 100003, 100019, 100043, 100049, 100057, 100069, 100103, 100109, 983100129, 100151, 100153, 100169, 100183, 100189, 100193, 100207, 100213, 100237, 984100267, 100271, 100279, 100291, 100297, 100313, 100333, 100343, 100357, 100361, 985100363, 100379, 100391, 100393, 100403, 100411, 100417, 100447, 100459, 100469, 986100483, 100493, 100501, 100511, 100517, 100519, 100523, 100537, 100547, 100549, 987100559, 100591, 100609, 100613, 100621, 100649, 100669, 100673, 100693, 100699, 988100703, 100733, 100741, 100747, 100769, 100787, 100799, 100801, 100811, 100823, 989100829, 100847, 100853, 100907, 100913, 100927, 100931, 100937, 100943, 100957, 990100981, 100987, 100999, 101009, 101021, 101027, 101051, 101063, 101081, 101089, 991101107, 101111, 101113, 101117, 101119, 101141, 101149, 101159, 101161, 101173, 992101183, 101197, 101203, 101207, 101209, 101221, 101267, 101273, 101279, 101281, 993101287, 101293, 101323, 101333, 101341, 101347, 101359, 101363, 101377, 101383, 994101399, 101411, 101419, 101429, 101449, 101467, 101477, 101483, 101489, 101501, 995101503, 101513, 101527, 101531, 101533, 101537, 101561, 101573, 101581, 101599, 996101603, 101611, 101627, 101641, 101653, 101663, 101681, 101693, 101701, 101719, 997101723, 101737, 101741, 101747, 101749, 101771, 101789, 101797, 101807, 101833, 998101837, 101839, 101863, 101869, 101873, 101879, 101891, 101917, 101921, 101929, 999101939, 101957, 101963, 101977, 101987, 101999, 102001, 102013, 102019, 102023, 1000102031, 102043, 102059, 102061, 102071, 102077, 102079, 102101, 102103, 102107, 1001102121, 102139, 102149, 102161, 102181, 102191, 102197, 102199, 102203, 102217, 1002102229, 102233, 102241, 102251, 102253, 102259, 102293, 102299, 102301, 102317, 1003102329, 102337, 102359, 102367, 102397, 102407, 102409, 102433, 102437, 102451, 1004102461, 102481, 102497, 102499, 102503, 102523, 102533, 102539, 102547, 102551, 1005102559, 102563, 102587, 102593, 102607, 102611, 102643, 102647, 102653, 102667, 1006102673, 102677, 102679, 102701, 102761, 102763, 102769, 102793, 102797, 102811, 1007102829, 102841, 102859, 102871, 102877, 102881, 102911, 102913, 102929, 102931, 1008102953, 102967, 102983, 103001, 103007, 103043, 103049, 103067, 103069, 103079, 1009103087, 103091, 103093, 103099, 103123, 103141, 103171, 103177, 103183, 103217, 1010103231, 103237, 103289, 103291, 103307, 103319, 103333, 103349, 103357, 103387, 1011103391, 103393, 103399, 103409, 103421, 103423, 103451, 103457, 103471, 103483, 1012103511, 103529, 103549, 103553, 103561, 103567, 103573, 103577, 103583, 103591, 1013103613, 103619, 103643, 103651, 103657, 103669, 103681, 103687, 103699, 103703, 1014103723, 103769, 103787, 103801, 103811, 103813, 103837, 103841, 103843, 103867, 1015103889, 103903, 103913, 103919, 103951, 103963, 103967, 103969, 103979, 103981, 1016103991, 103993, 103997, 104003, 104009, 104021, 104033, 104047, 104053, 104059, 1017104087, 104089, 104107, 104113, 104119, 104123, 104147, 104149, 104161, 104173, 1018104179, 104183, 104207, 104231, 104233, 104239, 104243, 104281, 104287, 104297, 1019104309, 104311, 104323, 104327, 104347, 104369, 104381, 104383, 104393, 104399, 1020104417, 104459, 104471, 104473, 104479, 104491, 104513, 104527, 104537, 104543, 1021104549, 104551, 104561, 104579, 104593, 104597, 104623, 104639, 104651, 104659, 1022104677, 104681, 104683, 104693, 104701, 104707, 104711, 104717, 104723, 104729, 1023] 1024 1025 1026 1027### Ctrl-C handler 1028def handler(signal, frame): 1029 sys.tracebacklimit = 0 1030 exit(0) 1031 1032DEFBUFSIZE=32768 1033 1034def get_cpu_count(): 1035 """ 1036 Try and estimate the number of CPU on the host. First using multiprocessing 1037 native function, other using content of /proc/cpuinfo. If none of those 1038 methods did work, 4 is returned. 1039 """ 1040 try: 1041 import multiprocessing 1042 cpucount = multiprocessing.cpu_count() 1043 except: 1044 try: 1045 s = open("/proc/cpuinfo").read() 1046 cpucount = int(s.split('processor')[-1].split(":")[1].split("\n")[0]) 1047 cpucount += 1 1048 except: 1049 cpucount = 4 1050 return cpucount 1051 1052# Simple helper to remove comments from a C program 1053def C_comment_remover(text): 1054 def replacer(match): 1055 s = match.group(0) 1056 if s.startswith('/'): 1057 return " " # note: a space and not an empty string 1058 else: 1059 return s 1060 regexp = r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"' 1061 pattern = re.compile(regexp, re.DOTALL | re.MULTILINE) 1062 return re.sub(pattern, replacer, text) 1063 1064 1065def egcd(b, n): 1066 x0, x1, y0, y1 = 1, 0, 0, 1 1067 while n != 0: 1068 q, b, n = b // n, n, b % n 1069 x0, x1 = x1, x0 - q * x1 1070 y0, y1 = y1, y0 - q * y1 1071 return b, x0, y0 1072 1073def modinv(a, m): 1074 g, x, y = egcd(a, m) 1075 if g != 1: 1076 raise Exception('modular inverse does not exist') 1077 else: 1078 return x % m 1079 1080def is_probprime(n): 1081 # ensure n is odd 1082 if n % 2 == 0: 1083 return False 1084 # write n-1 as 2**s * d 1085 # repeatedly try to divide n-1 by 2 1086 s = 0 1087 d = n-1 1088 while True: 1089 quotient, remainder = divmod(d, 2) 1090 if remainder == 1: 1091 break 1092 s += 1 1093 d = quotient 1094 assert(2**s * d == n-1) 1095 # test the base a to see whether it is a witness for the compositeness of n 1096 def try_composite(a): 1097 if pow(a, d, n) == 1: 1098 return False 1099 for i in range(s): 1100 if pow(a, 2**i * d, n) == n-1: 1101 return False 1102 return True # n is definitely composite 1103 for i in range(5): 1104 a = random.randrange(2, n) 1105 if try_composite(a): 1106 return False 1107 return True # no base tested showed n as composite 1108 1109def compute_monty_coef(nn_p, p_bitsize): 1110 """ 1111 Compute montgomery coeff r, r^2 and mpinv. p_bitsize is the size 1112 of p in bits. It is expected to be a multiple of word 1113 bit size. 1114 """ 1115 r = (1 << p_bitsize) % nn_p 1116 r_square = (1 << (2 * p_bitsize)) % nn_p 1117 mpinv = 2**wlen - (modinv(nn_p, 2**wlen)) 1118 return r, r_square, mpinv 1119 1120def compute_div_coef(nn_p, p_bitsize): 1121 """ 1122 Compute division coeffs p_normalized, p_shift and p_reciprocal. 1123 """ 1124 tmp = nn_p 1125 cnt = 0 1126 while tmp != 0: 1127 tmp = tmp >> 1 1128 cnt += 1 1129 pshift = p_bitsize - cnt 1130 nn_pnorm = nn_p << pshift 1131 B = 2**wlen 1132 prec = B**3 // ((nn_pnorm >> (p_bitsize - 2*wlen)) + 1) - B 1133 return pshift, nn_pnorm, prec 1134 1135def getbitlen(bint): 1136 """ 1137 Returns the number of bits encoding an integer 1138 """ 1139 if bint == 0: 1140 return 1 1141 else: 1142 return int(bint).bit_length() 1143 1144def getwlenbitlen(bint, wlen): 1145 """ 1146 Returns the number of bits encoding an integer 1147 """ 1148 rounded_wlen_bitlen = ((getbitlen(bint) + wlen - 1) // wlen) * wlen 1149 if(rounded_wlen_bitlen == 0): 1150 rounded_wlen_bitlen = wlen 1151 return rounded_wlen_bitlen 1152 1153def legendre_symbol(a, p): 1154 ls = pow(a, (p - 1) // 2, p) 1155 return -1 if ls == p - 1 else ls 1156 1157# Tonelli-Shanks algorithm to find square roots 1158# over prime fields 1159def mod_sqrt(a, p): 1160 # Simple cases 1161 if legendre_symbol(a, p) != 1: 1162 # No quadratic residue 1163 return None 1164 elif a == 0: 1165 return 0 1166 elif p == 2: 1167 return a 1168 elif p % 4 == 3: 1169 return pow(a, (p + 1) // 4, p) 1170 s = p - 1 1171 e = 0 1172 while s % 2 == 0: 1173 s = s // 2 1174 e += 1 1175 n = 2 1176 while legendre_symbol(n, p) != -1: 1177 n += 1 1178 x = pow(a, (s + 1) // 2, p) 1179 b = pow(a, s, p) 1180 g = pow(n, s, p) 1181 r = e 1182 while True: 1183 t = b 1184 m = 0 1185 for m in xrange(r): 1186 if t == 1: 1187 break 1188 t = pow(t, 2, p) 1189 if m == 0: 1190 return x 1191 gs = pow(g, 2 ** (r - m - 1), p) 1192 g = (gs * gs) % p 1193 x = (x * gs) % p 1194 b = (b * g) % p 1195 r = m 1196 1197def format_int_string(bint, wlen): 1198 """ 1199 Returns the string format of an integer rounded to wlen 1200 """ 1201 rounded_bytelen = (wlen/8) * ((getbitlen(bint) + wlen - 1) // wlen) 1202 # Special case of zero bit length 1203 if(rounded_bytelen == 0): 1204 rounded_bytelen = wlen//8 1205 return (("%%0%dx" % (2 * rounded_bytelen)) % bint) 1206 1207def get_random_bigint(wlen, maxwlensize): 1208 nn_nwords = random.randint(1, maxwlensize) 1209 nn_maxval = 2 ** (nn_nwords * wlen) - 1 1210 return random.randint(0, nn_maxval) 1211 1212# Eratostene sieve for fast candidates 1213def get_random_prime_sieve_candidate(wlen, maxwlensize): 1214 global first_primes_list 1215 while True: 1216 # Choose a random odd number 1217 r = get_random_bigint(wlen, maxwlensize) | 1 1218 for divisor in first_primes_list: 1219 if (r % divisor) == 0 and (divisor**2 <= r): 1220 break 1221 else: 1222 # r is a suitable candidate 1223 return r 1224 1225def get_random_prime(wlen, maxwlensize): 1226 while True: 1227 # Get a random integer 1228 r = get_random_prime_sieve_candidate(wlen, maxwlensize) 1229 # Check its primality 1230 if is_probprime(r): 1231 return r 1232 1233if ((len(sys.argv) != 5) and (len(sys.argv) != 6)): 1234 sys.stderr.write("Usage: %s outfile wlen ntests [tests]\n" % sys.argv[0]) 1235 sys.stderr.write("with\n") 1236 sys.stderr.write(" outfile: file in which generated tests will be stored\n") 1237 sys.stderr.write(" wlen : target architecture word length in bits (64, 32 or 16)\n") 1238 sys.stderr.write(" maxlen : maximum bit length of tests (e.g. 521 bits, ...)\n") 1239 sys.stderr.write(" ntests : a multiplier for the number of tests to perform\n") 1240 sys.stderr.write(" tests : (optional) specific tests to perform (regexp opcodes) OR\n") 1241 sys.stderr.write(" a '.c' file where to get the implemented tests. filename\n") 1242 sys.stderr.write(" is given using e.g. file=fp_pow.c\n") 1243 sys.exit(-1) 1244 1245testfile = sys.argv[1] 1246wlen = int(sys.argv[2]) 1247maxlen = int(sys.argv[3]) 1248ntests = int(sys.argv[4]) 1249 1250nn_logical_tests = ["NN_SHIFT_RIGHT", "NN_SHIFT_LEFT", "NN_ROTATE_RIGHT", "NN_ROTATE_LEFT", 1251 "NN_AND", "NN_XOR", "NN_OR", "NN_NOT"] 1252nn_addition_tests = ["NN_ADD", "NN_SUB", "NN_INC", "NN_DEC", "NN_MOD_ADD", "NN_MOD_SUB", "NN_MOD_INC", "NN_MOD_DEC"] 1253nn_mul_tests = ["NN_MUL", "NN_SQR", "NN_MUL_REDC1", "NN_COEF_REDC1", "NN_COEF_DIV", "NN_MOD_MUL", "NN_MOD_POW"] 1254nn_div_tests = ["NN_MOD", "NN_DIVREM", "NN_MODINV", "NN_MODINV_2EXP", "NN_XGCD", "NN_GCD"] 1255 1256nn_tests = nn_logical_tests + nn_addition_tests + nn_mul_tests + nn_div_tests 1257 1258fp_add_tests = ["FP_ADD", "FP_SUB"] 1259fp_mul_tests = ["FP_MUL", "FP_SQR", "FP_DIV", "FP_MUL_MONTY", "FP_SQR_MONTY", "FP_POW"] 1260fp_sqrt_tests = ["FP_SQRT"] 1261 1262fp_tests = fp_add_tests + fp_mul_tests + fp_sqrt_tests 1263 1264all_tests = nn_tests + fp_tests 1265 1266# Get optional specific parameters 1267asked_tests = all_tests 1268if (len(sys.argv) == 6): 1269 # Do we have a .c file given as input? 1270 if (sys.argv[5])[:5] == "file=": 1271 file_name = (sys.argv[5])[5:] 1272 # Open the .c file 1273 C_string = C_comment_remover(open(file_name, 'r').read()) 1274 # Grep the interesting tests 1275 lines = C_string.split("\n") 1276 asked_tests = [] 1277 for line in lines: 1278 if line[:13] == "GENERIC_TEST(": 1279 # Get second argument, which is the opcode 1280 the_test = line.split(",")[1].replace(" ", "") 1281 asked_tests += [the_test] 1282 # We have a list of opcode regexps 1283 else: 1284 def check_regexp(regexp, string): 1285 return re.match(regexp+"$", string) 1286 asked_tests = [] 1287 asked_tests_regexps = ((sys.argv[5]).replace(" ", "")).split(",") 1288 # Check for regexps 1289 for regexp in asked_tests_regexps: 1290 # Asked operations must be known 1291 match = [x for x in all_tests if check_regexp(regexp, x)] 1292 if match == []: 1293 print "Warning: regexp matches no known operation ", regexp 1294 asked_tests += match 1295 1296# Unnecessary test (we can keep it though) 1297if len(list(set(asked_tests) & set(all_tests))) != len(asked_tests): 1298 print "Error: unknown asked tests ", list(set(asked_tests) - set(all_tests)) 1299 exit(-1) 1300 1301# Delta to use on word boundaries. 1302WORD_BOUNDARY_DELTA=3 1303 1304# Max size (in words) of input numbers (nn, fp) on which to perform tests 1305MAX_INPUT_PARAM_WLEN= ((maxlen + wlen - 1) // wlen) 1306 1307test_funcs = { } 1308 1309# Generate tests for NN_SHIFT_RIGHT and NN_SHIFT_LEFT operations. 1310def test_NN_SHIFT(op): 1311 nn_nwords = random.randint(1, MAX_INPUT_PARAM_WLEN) 1312 nn_maxval = 2 ** (nn_nwords * wlen) - 1 1313 nn_nbits = nn_nwords * wlen 1314 1315 nn_val = random.randint(0, nn_maxval) 1316 1317 res = [] 1318 1319 # try and consider all possible words boundary on input ... 1320 for boundary in range(0, (nn_nwords + 1) * wlen, wlen): 1321 # and generate shift for bitcount in an interval around 1322 # that boundary, i.e. [boundary - delta, boundary + delta] 1323 min_cnt = max(0, boundary - WORD_BOUNDARY_DELTA) 1324 max_cnt = min(nn_nbits, boundary + WORD_BOUNDARY_DELTA) 1325 cnt = random.randint(min_cnt, max_cnt); 1326 msk = nn_maxval 1327 1328 # we try different bitlen for output 1329 for outbitlen in [boundary - wlen, boundary, boundary + wlen]: 1330 if outbitlen <= wlen: 1331 outbitlen = wlen 1332 1333 # Depending on the type of shift operation we consider, 1334 # we adapt the & mask 1335 if (op == "NN_SHIFT_RIGHT_FIXEDLEN"): # NN_SHIFT_RIGHT_FIXEDLEN 1336 msk = (2 ** outbitlen) - 1 1337 out = (nn_val >> cnt) & msk 1338 elif (op == "NN_SHIFT_LEFT_FIXEDLEN"): # NN_SHIFT_LEFT_FIXEDLEN 1339 msk = (2 ** outbitlen) - 1 1340 out = (nn_val << cnt) & msk 1341 elif (op == "NN_SHIFT_RIGHT"): # NN_SHIFT_RIGHT 1342 outbitlen = nn_nbits 1343 msk = (2 ** outbitlen) - 1 1344 out = (nn_val >> cnt) & msk 1345 else: # NN_SHIFT_LEFT 1346 outbitlen = nn_nbits + cnt 1347 # Round the bit length to the word boundary 1348 outbitlen = ((outbitlen + wlen - 1) // wlen) * wlen 1349 msk = (2 ** outbitlen) - 1 1350 out = (nn_val << cnt) & msk 1351 1352 fmt = "%s nnu %s %s %d\n" 1353 res.append(fmt % (op, format_int_string(out, wlen), format_int_string(nn_val, wlen), cnt)) 1354 1355 return res 1356 1357test_funcs["NN_SHIFT_RIGHT_FIXEDLEN"] = test_NN_SHIFT 1358test_funcs["NN_SHIFT_LEFT_FIXEDLEN"] = test_NN_SHIFT 1359test_funcs["NN_SHIFT_RIGHT"] = test_NN_SHIFT 1360test_funcs["NN_SHIFT_LEFT"] = test_NN_SHIFT 1361 1362# Generate tests for NN_ROTATE_LEFT and NN_ROTATE_RIGHT operations. 1363def test_NN_ROTATE(op): 1364 # random value for both input numbers 1365 nn_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1366 bitlen = random.randint(1, getbitlen(nn_val)) 1367 cnt = random.randint(0, bitlen-1) 1368 1369 res = [] 1370 1371 if (op == "NN_ROTATE_LEFT"): # NN_ROTATE_LEFT 1372 nn_exp_res = ((nn_val << cnt) ^ (nn_val >> (bitlen - cnt))) & (2**bitlen - 1) 1373 else: # NN_ROTATE_RIGHT 1374 nn_exp_res = ((nn_val >> cnt) ^ (nn_val << (bitlen - cnt))) & (2**bitlen - 1) 1375 1376 fmt = "%s nnuu %s %s %d %d\n" 1377 res.append(fmt % (op, format_int_string(nn_exp_res, wlen), format_int_string(nn_val, wlen), cnt, bitlen)) 1378 1379 return res 1380 1381test_funcs["NN_ROTATE_LEFT"] = test_NN_ROTATE 1382test_funcs["NN_ROTATE_RIGHT"] = test_NN_ROTATE 1383 1384 1385# Generate tests for NN_XOR, NN_OR and NN_AND operations. 1386def test_NN_XOR_OR_AND(op): 1387 # random value for both input numbers 1388 nn1_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1389 nn2_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1390 1391 res = [] 1392 1393 if (op == "NN_XOR"): # NN_XOR 1394 nn_exp_res = nn1_val ^ nn2_val 1395 elif (op == "NN_OR"): # NN_OR 1396 nn_exp_res = nn1_val | nn2_val 1397 else: # NN_AND 1398 nn_exp_res = nn1_val & nn2_val 1399 1400 fmt = "%s nnn %s %s %s\n" 1401 res.append(fmt % (op, format_int_string(nn1_val, wlen), format_int_string(nn2_val, wlen), format_int_string(nn_exp_res, wlen))) 1402 1403 return res 1404 1405test_funcs["NN_XOR"] = test_NN_XOR_OR_AND 1406test_funcs["NN_OR"] = test_NN_XOR_OR_AND 1407test_funcs["NN_AND"] = test_NN_XOR_OR_AND 1408 1409 1410def test_NN_NOT(op): 1411 """ Generate tests for NN_NOT """ 1412 nn_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1413 1414 res = [] 1415 1416 # python sucks at computing logical not. It generates a two's complement 1417 # representation, which mays result in a negative value i.e. not what we 1418 # are looking for. 1419 nn_exp_res = ((2 ** getwlenbitlen(nn_val, wlen)) - 1) & (~nn_val) 1420 1421 fmt = "%s nn %s %s\n" 1422 res.append(fmt % (op, format_int_string(nn_val, wlen), format_int_string(nn_exp_res, wlen))) 1423 1424 return res 1425 1426test_funcs["NN_NOT"] = test_NN_NOT 1427 1428 1429def test_NN_ADD_SUB(op): 1430 """ Generate tests for NN_ADD and NN_SUB """ 1431 # Get two random big num 1432 nn_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1433 nn_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1434 1435 # Compute the result depending on the operation 1436 if (op == "NN_ADD"): 1437 res = nn_val1 + nn_val2 1438 else: 1439 if (nn_val1 < nn_val2): 1440 tmp = nn_val1 1441 nn_val1 = nn_val2 1442 nn_val2 = tmp 1443 res = nn_val1 - nn_val2 1444 nn_exp_res = res 1445 1446 fmt = "%s nnn %s %s %s\n" 1447 s = fmt % (op, format_int_string(nn_val1, wlen), format_int_string(nn_val2, wlen), format_int_string(nn_exp_res, wlen)) 1448 1449 return [ s ] 1450 1451test_funcs["NN_ADD"] = test_NN_ADD_SUB 1452test_funcs["NN_SUB"] = test_NN_ADD_SUB 1453 1454 1455def test_NN_INC_DEC(op): 1456 """ Generate tests for NN_INC and NN_DEC """ 1457 nn_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1458 1459 # Compute the result depending on the operation 1460 if (op == "NN_INC"): 1461 res = nn_val + 1 1462 else: 1463 res = nn_val - 1 1464 nn_exp_res = res 1465 1466 fmt = "%s nn %s %s\n" 1467 s = fmt % (op, format_int_string(nn_val, wlen), format_int_string(nn_exp_res, wlen)) 1468 1469 return [ s ] 1470 1471test_funcs["NN_INC"] = test_NN_INC_DEC 1472test_funcs["NN_DEC"] = test_NN_INC_DEC 1473 1474def test_NN_MOD_ADD_SUB(op): 1475 """ Generate tests for modular NN_ADD and NN_SUB """ 1476 # Get three random big num 1477 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1478 nn_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1479 nn_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1480 1481 # Compute the result depending on the operation 1482 if (op == "NN_MOD_ADD"): 1483 res = (nn_val1 + nn_val2) % nn_mod 1484 else: 1485 if (nn_val1 < nn_val2): 1486 tmp = nn_val1 1487 nn_val1 = nn_val2 1488 nn_val2 = tmp 1489 res = (nn_val1 - nn_val2) % nn_mod 1490 nn_exp_res = res 1491 1492 fmt = "%s nnnn %s %s %s %s\n" 1493 s = fmt % (op, format_int_string(nn_val1, wlen), format_int_string(nn_val2, wlen), format_int_string(nn_mod, wlen), format_int_string(nn_exp_res, wlen)) 1494 1495 return [ s ] 1496 1497test_funcs["NN_MOD_ADD"] = test_NN_MOD_ADD_SUB 1498test_funcs["NN_MOD_SUB"] = test_NN_MOD_ADD_SUB 1499 1500def test_NN_MOD_INC_DEC(op): 1501 """ Generate tests for NN_MOD_INC and NN_MOD_DEC """ 1502 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1503 nn_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1504 1505 # Compute the result depending on the operation 1506 if (op == "NN_MOD_INC"): 1507 res = (nn_val + 1) % nn_mod 1508 else: 1509 if nn_val == 0: 1510 nn_val = nn_val + 1 1511 res = (nn_val - 1) % nn_mod 1512 nn_exp_res = res 1513 1514 fmt = "%s nnn %s %s %s\n" 1515 s = fmt % (op, format_int_string(nn_val, wlen), format_int_string(nn_mod, wlen), format_int_string(nn_exp_res, wlen)) 1516 1517 return [ s ] 1518 1519test_funcs["NN_MOD_INC"] = test_NN_MOD_INC_DEC 1520test_funcs["NN_MOD_DEC"] = test_NN_MOD_INC_DEC 1521 1522 1523def test_NN_MUL_SQR(op): 1524 """ Generate tests for NN_MUL and NN_SQR """ 1525 # random value for input numbers 1526 nn_in1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1527 nn_in2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1528 1529 if (op == "NN_MUL"): 1530 out = nn_in1 * nn_in2 1531 1532 fmt = "%s nnnu %s %s %s\n" 1533 s = fmt % (op, format_int_string(out, wlen), format_int_string(nn_in1, wlen), format_int_string(nn_in2, wlen)) 1534 else: 1535 out = nn_in1 * nn_in1 1536 1537 fmt = "%s nnu %s %s\n" 1538 s = fmt % (op, format_int_string(out, wlen), format_int_string(nn_in1, wlen)) 1539 1540 return [ s ] 1541 1542test_funcs["NN_MUL"] = test_NN_MUL_SQR 1543test_funcs["NN_SQR"] = test_NN_MUL_SQR 1544 1545def test_NN_MOD_MUL(op): 1546 """ Generate tests for modular NN_MOD_MUL """ 1547 # Get three random big num 1548 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1549 nn_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1550 nn_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1551 1552 # Compute the result depending on the operation 1553 res = (nn_val1 * nn_val2) % nn_mod 1554 nn_exp_res = res 1555 1556 fmt = "%s nnnn %s %s %s %s\n" 1557 s = fmt % (op, format_int_string(nn_val1, wlen), format_int_string(nn_val2, wlen), format_int_string(nn_mod, wlen), format_int_string(nn_exp_res, wlen)) 1558 1559 return [ s ] 1560 1561test_funcs["NN_MOD_MUL"] = test_NN_MOD_MUL 1562 1563def test_NN_MOD_POW(op): 1564 """ Generate tests for modular NN_MOD_POW """ 1565 # Get three random big num 1566 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1567 nn_base = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1568 nn_exp = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1569 1570 # Compute the result depending on the operation 1571 res = pow(nn_base, nn_exp, nn_mod) 1572 nn_exp_res = res 1573 1574 fmt = "%s nnnn %s %s %s %s\n" 1575 s = fmt % (op, format_int_string(nn_base, wlen), format_int_string(nn_exp, wlen), format_int_string(nn_mod, wlen), format_int_string(nn_exp_res, wlen)) 1576 1577 return [ s ] 1578 1579test_funcs["NN_MOD_POW"] = test_NN_MOD_POW 1580 1581 1582def test_NN_MOD(op): 1583 """ Generate tests for NN_MOD """ 1584 # random value for input numbers 1585 nn_c = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1586 nn_d = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1587 1588 nn_exp_r = nn_c % nn_d 1589 1590 fmt = "%s nnn %s %s %s\n" 1591 s = fmt % (op, format_int_string(nn_exp_r, wlen), format_int_string(nn_c, wlen), format_int_string(nn_d, wlen)) 1592 1593 return [ s ] 1594 1595test_funcs["NN_MOD"] = test_NN_MOD 1596 1597def test_NN_DIVREM(op): 1598 """ Generate tests for NN_DIVREM """ 1599 # random value for input numbers with second one non zero 1600 nn_c = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1601 nn_d = 0 1602 while nn_d == 0: 1603 nn_d = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1604 1605 nn_exp_q = (nn_c // nn_d) 1606 nn_exp_r = nn_c % nn_d 1607 1608 fmt = "%s nnnn %s %s %s %s\n" 1609 s = fmt % (op, format_int_string(nn_exp_q, wlen), format_int_string(nn_exp_r, wlen), format_int_string(nn_c, wlen), format_int_string(nn_d, wlen)) 1610 1611 return [ s ] 1612 1613test_funcs["NN_DIVREM"] = test_NN_DIVREM 1614 1615def test_NN_XGCD(op): 1616 """ Generate tests for NN_XGCD """ 1617 # random value for input numbers 1618 nn_a = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1619 nn_b = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1620 1621 (nn_exp_g, nn_exp_u, nn_exp_v) = egcd(nn_a, nn_b) 1622 # Check sign of u and v and adapt output 1623 if nn_exp_u < 0: 1624 sign = -1 1625 nn_exp_u = (((2 ** getbitlen(nn_exp_u)) - 1) & (~nn_exp_u)) + 1 1626 else: 1627 sign = 1 1628 nn_exp_v = (((2 ** getbitlen(nn_exp_v)) - 1) & (~nn_exp_v)) + 1 1629 fmt = "%s nnnnns %s %s %s %s %s %d\n" 1630 s = fmt % (op, format_int_string(nn_exp_g, wlen), format_int_string(nn_exp_u, wlen), format_int_string(nn_exp_v, wlen), format_int_string(nn_a, wlen), format_int_string(nn_b, wlen), sign) 1631 1632 return [ s ] 1633 1634test_funcs["NN_XGCD"] = test_NN_XGCD 1635 1636def test_NN_GCD(op): 1637 """ Generate tests for NN_GCD """ 1638 # random value for input numbers 1639 nn_a = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1640 nn_b = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1641 1642 (nn_exp_g, nn_exp_u, nn_exp_v) = egcd(nn_a, nn_b) 1643 1644 (nn_exp_g, nn_exp_u, nn_exp_v) = egcd(nn_a, nn_b) 1645 # Check sign of u and v and adapt output 1646 if nn_exp_u < 0: 1647 sign = -1 1648 else: 1649 sign = 1 1650 1651 fmt = "%s nnns %s %s %s %d\n" 1652 s = fmt % (op, format_int_string(nn_exp_g, wlen), format_int_string(nn_a, wlen), format_int_string(nn_b, wlen), sign) 1653 1654 return [ s ] 1655 1656test_funcs["NN_GCD"] = test_NN_GCD 1657 1658def test_NN_MODINV(op): 1659 """ Generate tests for NN_MODINV """ 1660 # random value for input numbers, first one non zero 1661 nn_x = 0 1662 while nn_x == 0: 1663 nn_x = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1664 nn_m = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) 1665 1666 try: 1667 nn_exp_v = modinv(nn_x, nn_m) 1668 exp_r = 0 1669 except Exception: 1670 nn_exp_v = 0 1671 exp_r = -1 1672 1673 fmt = "%s nnns %s %s %s %d\n" 1674 s = fmt % (op, format_int_string(nn_exp_v, wlen), format_int_string(nn_x, wlen), format_int_string(nn_m, wlen), exp_r) 1675 1676 return [ s ] 1677 1678test_funcs["NN_MODINV"] = test_NN_MODINV 1679 1680def test_NN_MODINV_2EXP(op): 1681 """ Generate tests for NN_MODINV_2EXP """ 1682 # random value for input number, must be odd 1683 nn_x = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1684 exp = random.randint(1, MAX_INPUT_PARAM_WLEN * wlen) 1685 1686 nn_exp_v = modinv(nn_x, 2**exp) 1687 isodd = 1 1688 if (nn_x % 2) == 0: 1689 isodd = 0 1690 1691 fmt = "%s nnus %s %s %d %d\n" 1692 s = fmt % (op, format_int_string(nn_exp_v, wlen), format_int_string(nn_x, wlen), exp, isodd) 1693 1694 return [ s ] 1695 1696test_funcs["NN_MODINV_2EXP"] = test_NN_MODINV_2EXP 1697 1698def test_NN_MUL_REDC1(op): 1699 """ Generate tests for NN_MUL_REDC1 """ 1700 # Odd modulus 1701 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1702 nn_r, nn_r_square, mpinv = compute_monty_coef(nn_mod, getwlenbitlen(nn_mod, wlen)) 1703 1704 # random value for input numbers modulo our random mod 1705 nn_in1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1706 nn_in2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_mod 1707 1708 # Montgomery multiplication computes in1 * in2 * r^-1 (mod) 1709 out = (nn_in1 * nn_in2 * modinv(nn_r, nn_mod)) % nn_mod 1710 1711 fmt = "%s nnnnu %s %s %s %s %d\n" 1712 s = fmt % (op, format_int_string(out, wlen), format_int_string(nn_in1, wlen), format_int_string(nn_in2, wlen), format_int_string(nn_mod, wlen), mpinv) 1713 1714 return [ s ] 1715 1716test_funcs["NN_MUL_REDC1"] = test_NN_MUL_REDC1 1717 1718def test_NN_COEF_REDC1(op): 1719 """ Generate tests for NN_COEF_REDC1 """ 1720 # Odd modulus 1721 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1722 # Get the results 1723 # Expand the modulus size if necessary 1724 if getwlenbitlen(nn_mod, wlen) == wlen: 1725 nn_r, nn_r_square, mpinv = compute_monty_coef(nn_mod, 2*getwlenbitlen(nn_mod, wlen)) 1726 else: 1727 nn_r, nn_r_square, mpinv = compute_monty_coef(nn_mod, getwlenbitlen(nn_mod, wlen)) 1728 1729 fmt = "%s nnnu %s %s %s %d\n" 1730 s = fmt % (op, format_int_string(nn_r, wlen), format_int_string(nn_r_square, wlen), format_int_string(nn_mod, wlen), mpinv) 1731 1732 return [ s ] 1733 1734test_funcs["NN_COEF_REDC1"] = test_NN_COEF_REDC1 1735 1736def test_NN_COEF_DIV(op): 1737 """ Generate tests for NN_COEF_DIV """ 1738 # Odd modulus 1739 nn_mod = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1740 # Get the results 1741 # Expand the modulus size if necessary 1742 if getwlenbitlen(nn_mod, wlen) == wlen: 1743 pshift, nn_pnorm, prec = compute_div_coef(nn_mod, 2*getwlenbitlen(nn_mod, wlen)) 1744 else: 1745 pshift, nn_pnorm, prec = compute_div_coef(nn_mod, getwlenbitlen(nn_mod, wlen)) 1746 1747 fmt = "%s nuun %s %d %d %s\n" 1748 s = fmt % (op, format_int_string(nn_pnorm, wlen), pshift, prec, format_int_string(nn_mod, wlen)) 1749 1750 return [ s ] 1751 1752test_funcs["NN_COEF_DIV"] = test_NN_COEF_DIV 1753 1754 1755# Helper to compute and export an Fp context 1756def format_fp_context(nn_p, wlen): 1757 nn_nbits = getwlenbitlen(nn_p, wlen) 1758 if nn_nbits == wlen: 1759 nn_nbits = 2 * wlen 1760 nn_r, nn_r_square, mpinv = compute_monty_coef(nn_p, nn_nbits) 1761 pshift, nn_pnorm, prec = compute_div_coef(nn_p, nn_nbits) 1762 f = "%%0%dx" % ((nn_nbits // 8) * 2) 1763 fmpinv = "%%0%dx" % (((wlen // 8)) * 2) 1764 return ("%s%s%s%s%s%s%s" % (f % nn_p, f % nn_r, f % nn_r_square, fmpinv % mpinv, 1765 fmpinv % pshift, f % nn_pnorm, fmpinv % prec)) 1766 1767def test_FP_ADD_SUB(op): 1768 """ Generate tests for FP_ADD_SUB """ 1769 # Use random odd number for faster generation 1770 nn_p = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1771 1772 # Get two random big num 1773 fp_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1774 fp_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1775 1776 # Compute the result depending on the operation 1777 if (op == "FP_ADD"): 1778 fp_exp_res = (fp_val1 + fp_val2) % nn_p 1779 else: 1780 fp_exp_res = (fp_val1 - fp_val2) % nn_p 1781 1782 fmt = "%s cfff %s %s %s %s\n" 1783 s = fmt % (op, format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val1, wlen), format_int_string(fp_val2, wlen)) 1784 1785 return [ s ] 1786 1787test_funcs["FP_ADD"] = test_FP_ADD_SUB 1788test_funcs["FP_SUB"] = test_FP_ADD_SUB 1789 1790def test_FP_DIV(op): 1791 """ Generate tests for FP_DIV """ 1792 # Get random prime 1793 # NOTE: since we use Fermat's little theorem for inversion, p 1794 # MUST be prime for DIV (while p is relaxed only to be odd for most 1795 # of the other operations). 1796 # Generate a random prime 1797 nn_p = get_random_prime(wlen, MAX_INPUT_PARAM_WLEN) 1798 1799 # Get two random big num 1800 fp_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1801 fp_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1802 1803 fp_exp_res = (fp_val1 * modinv(fp_val2, nn_p)) % nn_p 1804 1805 fmt = "%s cfff %s %s %s %s\n" 1806 s = fmt % (op,format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val1, wlen), format_int_string(fp_val2, wlen)) 1807 1808 return [ s ] 1809 1810test_funcs["FP_DIV"] = test_FP_DIV 1811 1812def test_FP_MUL_SQR(op): 1813 """ Generate tests for FP_MUL_SQR """ 1814 # Use random odd number for faster generation 1815 nn_p = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1816 1817 # Get two random big num 1818 fp_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1819 fp_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1820 1821 # Compute the result depending on the operation 1822 if (op == "FP_MUL") or (op == "FP_SQR"): 1823 if (op == "FP_MUL"): 1824 fp_exp_res = (fp_val1 * fp_val2) % nn_p 1825 else: 1826 fp_exp_res = (fp_val1 * fp_val1) % nn_p 1827 1828 if (op == "FP_SQR"): 1829 fmt = "%s cff %s %s %s\n" 1830 s = fmt % (op,format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val1, wlen)) 1831 else: 1832 fmt = "%s cfff %s %s %s %s\n" 1833 s = fmt % (op,format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val1, wlen), format_int_string(fp_val2, wlen)) 1834 1835 return [ s ] 1836 1837test_funcs["FP_MUL"] = test_FP_MUL_SQR 1838test_funcs["FP_SQR"] = test_FP_MUL_SQR 1839 1840 1841def test_FP_MUL_SQR_MONTY(op): 1842 """ Generate tests for FP_MUL_SQR_MONTY """ 1843 # Use random odd number for faster generation 1844 nn_p = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1845 if getwlenbitlen(nn_p, wlen) == wlen: 1846 nn_r, nn_r_square, mpinv = compute_monty_coef(nn_p, 2*getwlenbitlen(nn_p, wlen)) 1847 else: 1848 nn_r, nn_r_square, mpinv = compute_monty_coef(nn_p, getwlenbitlen(nn_p, wlen)) 1849 1850 # Get two random big num 1851 fp_val1 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1852 fp_val2 = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1853 # representations of fp_val1 and fp_val2 in Montgomery's world 1854 fp_val1_mont = (fp_val1 * nn_r ) % nn_p 1855 fp_val2_mont = (fp_val2 * nn_r ) % nn_p 1856 1857 1858 if (op == "FP_MUL_MONTY") or (op == "FP_SQR_MONTY"): 1859 if (op == "FP_MUL_MONTY"): 1860 fp_exp_res = (fp_val1_mont * fp_val2_mont * modinv(nn_r%nn_p, nn_p)) % nn_p 1861 else: 1862 fp_exp_res = (fp_val1_mont * fp_val1_mont * modinv(nn_r%nn_p, nn_p)) % nn_p 1863 1864 if (op == "FP_SQR"): 1865 fmt = "%s cff %s %s %s\n" 1866 s = fmt % (op, format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val1_mont, wlen)) 1867 else: 1868 fmt = "%s cfff %s %s %s %s\n" 1869 s = fmt % (op, format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val1_mont, wlen), format_int_string(fp_val2_mont, wlen)) 1870 1871 return [ s ] 1872 1873test_funcs["FP_MUL_MONTY"] = test_FP_MUL_SQR_MONTY 1874test_funcs["FP_SQR_MONTY"] = test_FP_MUL_SQR_MONTY 1875 1876 1877def test_FP_POW(op): 1878 """ Generate tests for FP_POW """ 1879 # Instead of random prime, use random odd number for faster generation 1880 nn_p = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) | 1 1881 1882 # Get two random big num 1883 fp_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1884 nn_exp = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1885 1886 fp_exp_res = pow(fp_val, nn_exp, nn_p) 1887 1888 fmt = "%s cffn %s %s %s %s\n" 1889 s = fmt % (op, format_fp_context(nn_p, wlen), format_int_string(fp_exp_res, wlen), format_int_string(fp_val, wlen), format_int_string(nn_exp, wlen)) 1890 1891 return [ s ] 1892 1893test_funcs["FP_POW"] = test_FP_POW 1894 1895 1896def test_FP_SQRT(op): 1897 """ Generate tests for FP_SQRT """ 1898 # Generate a random prime 1899 nn_p = get_random_prime(wlen, MAX_INPUT_PARAM_WLEN) 1900 1901 # Get a random big num in Fp 1902 fp_val = get_random_bigint(wlen, MAX_INPUT_PARAM_WLEN) % nn_p 1903 1904 # Compute the first square root 1905 fp_sqrt1 = mod_sqrt(fp_val, nn_p) 1906 # Compute the other square root 1907 if fp_sqrt1 != None: 1908 fp_sqrt2 = (-fp_sqrt1) % nn_p 1909 1910 fmt = "%s cfffs %s %s %s %s %s\n" 1911 if fp_sqrt1 != None: 1912 s = fmt % (op, format_fp_context(nn_p, wlen), format_int_string(fp_sqrt1, wlen), format_int_string(fp_sqrt2, wlen), format_int_string(fp_val, wlen), 0) 1913 else: 1914 s = fmt % (op, format_fp_context(nn_p, wlen), format_int_string(0, wlen), format_int_string(0, wlen), format_int_string(fp_val, wlen), -1) 1915 1916 return [ s ] 1917 1918test_funcs["FP_SQRT"] = test_FP_SQRT 1919 1920 1921 1922def do_test(sockfd, op, n): 1923 """ 1924 Do given test and send back result on given socket 1925 before leaving. 1926 """ 1927 res = [] 1928 for k in range(n): 1929 res += test_funcs[op](op) 1930 remain = "".join(res) 1931 while (remain): 1932 cur = remain[:DEFBUFSIZE] 1933 sockfd.send(cur) 1934 remain = remain[DEFBUFSIZE:] 1935 sockfd.close() 1936 1937 1938# The way we make generation parallel is by splitting ntests equally 1939# on the number of proc we have. 1940signal.signal(signal.SIGINT, handler) 1941 1942# ATM, we spawn as many processes as the number of tests we have. 1943# We adapt the output on stdout or regular file. 1944if testfile == "stdout": 1945 fd = sys.stdout 1946else: 1947 fd = open(testfile, "w") 1948numproc = get_cpu_count() 1949line = 0 1950 1951sys.stderr.write("[+] Dispatching our %d tests on %d proc\n" % (ntests, numproc)) 1952 1953for test in asked_tests: 1954 socks = [] 1955 1956 # Before forking, we need to be sure there is no 1957 # remaining data in file fd buffers, otherwise 1958 # those will end up being flushed by out childs 1959 # and create duplicates in the file. 1960 fd.flush() 1961 1962 n = max((ntests // numproc), 1) 1963 for k in range(0, ntests, n): 1964 # Create a pair of sockets for us and the child we'll spawn 1965 a, b = socket.socketpair() 1966 a.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, DEFBUFSIZE) 1967 b.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, DEFBUFSIZE) 1968 a.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, DEFBUFSIZE) 1969 b.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, DEFBUFSIZE) 1970 1971 # keep track of our socket 1972 socks.append(a) 1973 1974 # Double fork a helper to create the campaign for this specific 1975 # test. 1976 pid = os.fork() 1977 if pid != 0: 1978 os.waitpid(pid, 0) 1979 else: 1980 pid = os.fork() 1981 if pid != 0: 1982 sys.exit() 1983 else: 1984 a.close() 1985 # Properly seeding to avoid duplicate random generation 1986 random.seed(datetime.now()) 1987 do_test(b, test, n) 1988 sys.exit() 1989 1990 b.close() 1991 1992 # Now that we have fork all helpers, let's just wait until they are 1993 # done and read back the results to write them to file. 1994 while socks: 1995 tmp = select.select(socks, [], []) 1996 for s in tmp[0]: 1997 socks.remove(s) 1998 tmp = s.recv(DEFBUFSIZE) 1999 res = "" 2000 while tmp: 2001 res += tmp 2002 tmp = s.recv(DEFBUFSIZE) 2003 res = res.split('\n')[:-1] 2004 reslen = len(res) 2005 res = zip(range(reslen), res) 2006 fd.write("".join(map(lambda (x,y): "%d %s\n" % (x + line, y), res))) 2007 line += reslen 2008 2009fd.close() 2010