001/* 002 * $Id: PrimeList.java 4262 2012-10-21 13:24:47Z kredel $ 003 */ 004 005package edu.jas.arith; 006 007 008// import java.util.Random; 009import java.util.ArrayList; 010import java.util.Iterator; 011import java.util.List; 012 013import edu.jas.structure.Power; 014 015 016/** 017 * List of big primes. Provides an Iterator for generating prime numbers. 018 * Similar to ALDES/SAC2 SACPOL.PRIME list. 019 * 020 * @author Heinz Kredel See Knuth vol 2,page 390, for list of known primes. See 021 * also ALDES/SAC2 SACPOL.PRIME 022 */ 023 024public final class PrimeList implements Iterable<java.math.BigInteger> { 025 026 027 /** 028 * Range of probable primes. 029 */ 030 public static enum Range { 031 small, low, medium, large, mersenne 032 }; 033 034 035 /** 036 * Cache the val list for different size 037 */ 038 private volatile static List<java.math.BigInteger> SMALL_LIST = null; 039 040 041 private volatile static List<java.math.BigInteger> LOW_LIST = null; 042 043 044 private volatile static List<java.math.BigInteger> MEDIUM_LIST = null; 045 046 047 private volatile static List<java.math.BigInteger> LARGE_LIST = null; 048 049 050 private volatile static List<java.math.BigInteger> MERSENNE_LIST = null; 051 052 053 /** 054 * The list of probable primes in requested range. 055 */ 056 private List<java.math.BigInteger> val = null; 057 058 059 /** 060 * The last prime in the list. 061 */ 062 private java.math.BigInteger last; 063 064 065 /** 066 * Constructor for PrimeList. 067 */ 068 public PrimeList() { 069 this(Range.medium); 070 } 071 072 073 /** 074 * Constructor for PrimeList. 075 * 076 * @param r size range for primes. 077 */ 078 public PrimeList(Range r) { 079 // initialize with some known primes, see knuth (2,390) 080 switch (r) { 081 case small: 082 if (SMALL_LIST != null) { 083 val = SMALL_LIST; 084 } else { 085 val = new ArrayList<java.math.BigInteger>(50); 086 addSmall(); 087 SMALL_LIST = val; 088 } 089 break; 090 case low: 091 if (LOW_LIST != null) { 092 val = LOW_LIST; 093 } else { 094 val = new ArrayList<java.math.BigInteger>(50); 095 addLow(); 096 LOW_LIST = val; 097 } 098 break; 099 default: 100 case medium: 101 if (MEDIUM_LIST != null) { 102 val = MEDIUM_LIST; 103 } else { 104 val = new ArrayList<java.math.BigInteger>(50); 105 addMedium(); 106 MEDIUM_LIST = val; 107 } 108 break; 109 case large: 110 if (LARGE_LIST != null) { 111 val = LARGE_LIST; 112 } else { 113 val = new ArrayList<java.math.BigInteger>(50); 114 addLarge(); 115 LARGE_LIST = val; 116 } 117 break; 118 case mersenne: 119 if (MERSENNE_LIST != null) { 120 val = MERSENNE_LIST; 121 } else { 122 val = new ArrayList<java.math.BigInteger>(50); 123 addMersenne(); 124 MERSENNE_LIST = val; 125 } 126 break; 127 } 128 last = get(size() - 1); 129 } 130 131 132 /** 133 * Add small primes. 134 */ 135 private void addSmall() { 136 // really small 137 val.add(java.math.BigInteger.valueOf(2L)); 138 val.add(java.math.BigInteger.valueOf(3L)); 139 val.add(java.math.BigInteger.valueOf(5L)); 140 val.add(java.math.BigInteger.valueOf(7L)); 141 val.add(java.math.BigInteger.valueOf(11L)); 142 val.add(java.math.BigInteger.valueOf(13L)); 143 val.add(java.math.BigInteger.valueOf(17L)); 144 val.add(java.math.BigInteger.valueOf(19L)); 145 val.add(java.math.BigInteger.valueOf(23L)); 146 val.add(java.math.BigInteger.valueOf(29L)); 147 } 148 149 150 /** 151 * Add low sized primes. 152 */ 153 private void addLow() { 154 // 2^15-x 155 val.add(getLongPrime(15, 19)); 156 val.add(getLongPrime(15, 49)); 157 val.add(getLongPrime(15, 51)); 158 val.add(getLongPrime(15, 55)); 159 val.add(getLongPrime(15, 61)); 160 val.add(getLongPrime(15, 75)); 161 val.add(getLongPrime(15, 81)); 162 val.add(getLongPrime(15, 115)); 163 val.add(getLongPrime(15, 121)); 164 val.add(getLongPrime(15, 135)); 165 // 2^16-x 166 val.add(getLongPrime(16, 15)); 167 val.add(getLongPrime(16, 17)); 168 val.add(getLongPrime(16, 39)); 169 val.add(getLongPrime(16, 57)); 170 val.add(getLongPrime(16, 87)); 171 val.add(getLongPrime(16, 89)); 172 val.add(getLongPrime(16, 99)); 173 val.add(getLongPrime(16, 113)); 174 val.add(getLongPrime(16, 117)); 175 val.add(getLongPrime(16, 123)); 176 } 177 178 179 /** 180 * Add medium sized primes. 181 */ 182 private void addMedium() { 183 // 2^28-x 184 val.add(getLongPrime(28, 57)); 185 val.add(getLongPrime(28, 89)); 186 val.add(getLongPrime(28, 95)); 187 val.add(getLongPrime(28, 119)); 188 val.add(getLongPrime(28, 125)); 189 val.add(getLongPrime(28, 143)); 190 val.add(getLongPrime(28, 165)); 191 val.add(getLongPrime(28, 183)); 192 val.add(getLongPrime(28, 213)); 193 val.add(getLongPrime(28, 273)); 194 // 2^29-x 195 val.add(getLongPrime(29, 3)); 196 val.add(getLongPrime(29, 33)); 197 val.add(getLongPrime(29, 43)); 198 val.add(getLongPrime(29, 63)); 199 val.add(getLongPrime(29, 73)); 200 val.add(getLongPrime(29, 75)); 201 val.add(getLongPrime(29, 93)); 202 val.add(getLongPrime(29, 99)); 203 val.add(getLongPrime(29, 121)); 204 val.add(getLongPrime(29, 133)); 205 // 2^32-x 206 val.add(getLongPrime(32, 5)); 207 val.add(getLongPrime(32, 17)); 208 val.add(getLongPrime(32, 65)); 209 val.add(getLongPrime(32, 99)); 210 val.add(getLongPrime(32, 107)); 211 val.add(getLongPrime(32, 135)); 212 val.add(getLongPrime(32, 153)); 213 val.add(getLongPrime(32, 185)); 214 val.add(getLongPrime(32, 209)); 215 val.add(getLongPrime(32, 267)); 216 } 217 218 219 /** 220 * Add large sized primes. 221 */ 222 private void addLarge() { 223 // 2^59-x 224 val.add(getLongPrime(59, 55)); 225 val.add(getLongPrime(59, 99)); 226 val.add(getLongPrime(59, 225)); 227 val.add(getLongPrime(59, 427)); 228 val.add(getLongPrime(59, 517)); 229 val.add(getLongPrime(59, 607)); 230 val.add(getLongPrime(59, 649)); 231 val.add(getLongPrime(59, 687)); 232 val.add(getLongPrime(59, 861)); 233 val.add(getLongPrime(59, 871)); 234 // 2^60-x 235 val.add(getLongPrime(60, 93)); 236 val.add(getLongPrime(60, 107)); 237 val.add(getLongPrime(60, 173)); 238 val.add(getLongPrime(60, 179)); 239 val.add(getLongPrime(60, 257)); 240 val.add(getLongPrime(60, 279)); 241 val.add(getLongPrime(60, 369)); 242 val.add(getLongPrime(60, 395)); 243 val.add(getLongPrime(60, 399)); 244 val.add(getLongPrime(60, 453)); 245 // 2^63-x 246 val.add(getLongPrime(63, 25)); 247 val.add(getLongPrime(63, 165)); 248 val.add(getLongPrime(63, 259)); 249 val.add(getLongPrime(63, 301)); 250 val.add(getLongPrime(63, 375)); 251 val.add(getLongPrime(63, 387)); 252 val.add(getLongPrime(63, 391)); 253 val.add(getLongPrime(63, 409)); 254 val.add(getLongPrime(63, 457)); 255 val.add(getLongPrime(63, 471)); 256 // 2^64-x not possible 257 } 258 259 260 /** 261 * Add Mersenne sized primes. 262 */ 263 private void addMersenne() { 264 // 2^n-1 265 val.add(getMersennePrime(2)); 266 val.add(getMersennePrime(3)); 267 val.add(getMersennePrime(5)); 268 val.add(getMersennePrime(7)); 269 val.add(getMersennePrime(13)); 270 val.add(getMersennePrime(17)); 271 val.add(getMersennePrime(19)); 272 val.add(getMersennePrime(31)); 273 val.add(getMersennePrime(61)); 274 val.add(getMersennePrime(89)); 275 val.add(getMersennePrime(107)); 276 val.add(getMersennePrime(127)); 277 val.add(getMersennePrime(521)); 278 val.add(getMersennePrime(607)); 279 val.add(getMersennePrime(1279)); 280 val.add(getMersennePrime(2203)); 281 val.add(getMersennePrime(2281)); 282 val.add(getMersennePrime(3217)); 283 val.add(getMersennePrime(4253)); 284 val.add(getMersennePrime(4423)); 285 val.add(getMersennePrime(9689)); 286 val.add(getMersennePrime(9941)); 287 val.add(getMersennePrime(11213)); 288 val.add(getMersennePrime(19937)); 289 } 290 291 292 /** 293 * Method to compute a prime as 2**n - m. 294 * @param n power for 2. 295 * @param m for 2**n - m. 296 * @return 2**n - m 297 */ 298 public static java.math.BigInteger getLongPrime(int n, int m) { 299 long prime = 2; // knuth (2,390) 300 for (int i = 1; i < n; i++) { 301 prime *= 2; 302 } 303 prime -= m; 304 // System.out.println("p1 = " + prime); 305 return java.math.BigInteger.valueOf(prime); 306 } 307 308 309 /** 310 * Method to compute a Mersenne prime as 2**n - 1. 311 * @param n power for 2. 312 * @return 2**n - 1 313 */ 314 public static java.math.BigInteger getMersennePrime(int n) { 315 BigInteger t = new BigInteger(2); 316 BigInteger p = Power.positivePower(t, n); 317 p = p.subtract(new BigInteger(1)); 318 java.math.BigInteger prime = p.getVal(); 319 // System.out.println("p1 = " + prime); 320 return prime; 321 } 322 323 324 /** 325 * Check if the list contains really prime numbers. 326 */ 327 protected boolean checkPrimes() { 328 return checkPrimes(size()); 329 } 330 331 332 /** 333 * Check if the list contains really prime numbers. 334 */ 335 protected boolean checkPrimes(int n) { 336 boolean isPrime; 337 int i = 0; 338 for (java.math.BigInteger p : val) { 339 if (i++ >= n) { 340 break; 341 } 342 isPrime = p.isProbablePrime(63); 343 if (!isPrime) { 344 System.out.println("not prime = " + p); 345 return false; 346 } 347 } 348 return true; 349 } 350 351 352 /** 353 * toString. 354 */ 355 @Override 356 public String toString() { 357 return val.toString(); 358 } 359 360 361 /** 362 * size of current list. 363 */ 364 public int size() { 365 return val.size(); 366 } 367 368 369 /** 370 * get prime at index i. 371 */ 372 public java.math.BigInteger get(int i) { 373 java.math.BigInteger p; 374 if (i < size()) { 375 p = val.get(i); 376 } else { 377 p = last.nextProbablePrime(); 378 val.add(p); 379 last = p; 380 } 381 return p; 382 } 383 384 385 /** 386 * Iterator. 387 */ 388 public Iterator<java.math.BigInteger> iterator() { 389 return new Iterator<java.math.BigInteger>() { 390 391 392 int index = -1; 393 394 395 public boolean hasNext() { 396 return true; 397 } 398 399 400 public void remove() { 401 throw new UnsupportedOperationException("remove not implemented"); 402 } 403 404 405 public java.math.BigInteger next() { 406 index++; 407 return get(index); 408 } 409 }; 410 } 411 412}