001 /* 002 * $Id: PrimeList.java 3497 2011-01-20 21:30:04Z kredel $ 003 */ 004 005 package edu.jas.arith; 006 007 //import java.util.Random; 008 import java.util.List; 009 import java.util.Iterator; 010 import java.util.ArrayList; 011 012 //import edu.jas.util.StringUtil; 013 import edu.jas.structure.Power; 014 015 016 /** 017 * List of big primes. 018 * Provides an Iterator for generating prime numbers. 019 * Similar to ALDES/SAC2 SACPOL.PRIME list. 020 * @author Heinz Kredel 021 * See Knuth vol 2,page 390, for list of known primes. 022 * See ALDES/SAC2 SACPOL.PRIME 023 */ 024 025 public final class PrimeList implements Iterable<java.math.BigInteger> { 026 027 028 /** Range of probable primes. 029 */ 030 public static enum Range { small, medium, large, mersenne }; 031 032 033 /** The list of probable primes in requested range. 034 */ 035 protected final List<java.math.BigInteger> val 036 = new ArrayList<java.math.BigInteger>(50); 037 038 039 /** The last prime in the list. 040 */ 041 protected java.math.BigInteger last; 042 043 044 //private final static Random random = new Random(); 045 046 047 /** 048 * Constructor for PrimeList. 049 */ 050 public PrimeList() { 051 this(Range.medium); 052 } 053 054 055 /** 056 * Constructor for PrimeList. 057 * @param r size range for primes. 058 */ 059 public PrimeList(Range r) { 060 // initialize with some known primes, see knuth (2,390) 061 switch( r ) { 062 case small: addSmall(); 063 break; 064 default: 065 case medium: addMedium(); 066 break; 067 case large: addLarge(); 068 break; 069 case mersenne: addMersenne(); 070 break; 071 } 072 last = get( size()-1 ); 073 } 074 075 076 /** 077 * Add small primes. 078 */ 079 private void addSmall() { 080 // really small 081 val.add( new java.math.BigInteger(""+2) ); 082 val.add( new java.math.BigInteger(""+3) ); 083 val.add( new java.math.BigInteger(""+5) ); 084 val.add( new java.math.BigInteger(""+7) ); 085 val.add( new java.math.BigInteger(""+11) ); 086 val.add( new java.math.BigInteger(""+13) ); 087 val.add( new java.math.BigInteger(""+17) ); 088 val.add( new java.math.BigInteger(""+19) ); 089 val.add( new java.math.BigInteger(""+23) ); 090 } 091 092 093 /** 094 * Add medium sized primes. 095 */ 096 private void addMedium() { 097 // 2^28-x 098 val.add( getLongPrime(28,57) ); 099 val.add( getLongPrime(28,89) ); 100 val.add( getLongPrime(28,95) ); 101 val.add( getLongPrime(28,119) ); 102 val.add( getLongPrime(28,125) ); 103 val.add( getLongPrime(28,143) ); 104 val.add( getLongPrime(28,165) ); 105 val.add( getLongPrime(28,183) ); 106 val.add( getLongPrime(28,213) ); 107 val.add( getLongPrime(28,273) ); 108 // 2^29-x 109 val.add( getLongPrime(29,3) ); 110 val.add( getLongPrime(29,33) ); 111 val.add( getLongPrime(29,43) ); 112 val.add( getLongPrime(29,63) ); 113 val.add( getLongPrime(29,73) ); 114 val.add( getLongPrime(29,75) ); 115 val.add( getLongPrime(29,93) ); 116 val.add( getLongPrime(29,99) ); 117 val.add( getLongPrime(29,121) ); 118 val.add( getLongPrime(29,133) ); 119 } 120 121 122 /** 123 * Add large sized primes. 124 */ 125 private void addLarge() { 126 // 2^59-x 127 val.add( getLongPrime(59,55) ); 128 val.add( getLongPrime(59,99) ); 129 val.add( getLongPrime(59,225) ); 130 val.add( getLongPrime(59,427) ); 131 val.add( getLongPrime(59,517) ); 132 val.add( getLongPrime(59,607) ); 133 val.add( getLongPrime(59,649) ); 134 val.add( getLongPrime(59,687) ); 135 val.add( getLongPrime(59,861) ); 136 val.add( getLongPrime(59,871) ); 137 // 2^60-x 138 val.add( getLongPrime(60,93) ); 139 val.add( getLongPrime(60,107) ); 140 val.add( getLongPrime(60,173) ); 141 val.add( getLongPrime(60,179) ); 142 val.add( getLongPrime(60,257) ); 143 val.add( getLongPrime(60,279) ); 144 val.add( getLongPrime(60,369) ); 145 val.add( getLongPrime(60,395) ); 146 val.add( getLongPrime(60,399) ); 147 val.add( getLongPrime(60,453) ); 148 // 2^63-x 149 val.add( getLongPrime(63,25) ); 150 val.add( getLongPrime(63,165) ); 151 val.add( getLongPrime(63,259) ); 152 val.add( getLongPrime(63,301) ); 153 val.add( getLongPrime(63,375) ); 154 val.add( getLongPrime(63,387) ); 155 val.add( getLongPrime(63,391) ); 156 val.add( getLongPrime(63,409) ); 157 val.add( getLongPrime(63,457) ); 158 val.add( getLongPrime(63,471) ); 159 } 160 161 162 /** 163 * Add Mersenne sized primes. 164 */ 165 private void addMersenne() { 166 // 2^n-1 167 val.add( getMersennePrime(2) ); 168 val.add( getMersennePrime(3) ); 169 val.add( getMersennePrime(5) ); 170 val.add( getMersennePrime(7) ); 171 val.add( getMersennePrime(13) ); 172 val.add( getMersennePrime(17) ); 173 val.add( getMersennePrime(19) ); 174 val.add( getMersennePrime(31) ); 175 val.add( getMersennePrime(61) ); 176 val.add( getMersennePrime(89) ); 177 val.add( getMersennePrime(107) ); 178 val.add( getMersennePrime(127) ); 179 val.add( getMersennePrime(521) ); 180 val.add( getMersennePrime(607) ); 181 val.add( getMersennePrime(1279) ); 182 val.add( getMersennePrime(2203) ); 183 val.add( getMersennePrime(2281) ); 184 val.add( getMersennePrime(3217) ); 185 val.add( getMersennePrime(4253) ); 186 val.add( getMersennePrime(4423) ); 187 val.add( getMersennePrime(9689) ); 188 val.add( getMersennePrime(9941) ); 189 val.add( getMersennePrime(11213) ); 190 val.add( getMersennePrime(19937) ); 191 } 192 193 194 /** 195 * Method to compute a prime as 2**n - m. 196 * @param n power for 2. 197 * @param m for 2**n - m. 198 * @return 2**n - m 199 */ 200 public static java.math.BigInteger getLongPrime(int n, int m) { 201 long prime = 2; // knuth (2,390) 202 for ( int i = 1; i < n; i++ ) { 203 prime *= 2; 204 } 205 prime -= m; 206 //System.out.println("p1 = " + prime); 207 return new java.math.BigInteger(""+prime); 208 } 209 210 211 /** 212 * Method to compute a Mersenne prime as 2**n - 1. 213 * @param n power for 2. 214 * @return 2**n - 1 215 */ 216 public static java.math.BigInteger getMersennePrime(int n) { 217 BigInteger t = new BigInteger(2); 218 BigInteger p = Power.positivePower(t,n); 219 p = p.subtract(new BigInteger(1)); 220 java.math.BigInteger prime = p.getVal(); 221 //System.out.println("p1 = " + prime); 222 return prime; 223 } 224 225 226 /** 227 * Check if the list contains really prime numbers. 228 */ 229 protected boolean checkPrimes() { 230 return checkPrimes( size() ); 231 } 232 233 234 /** 235 * Check if the list contains really prime numbers. 236 */ 237 protected boolean checkPrimes(int n) { 238 boolean isPrime; 239 int i = 0; 240 for ( java.math.BigInteger p : val ) { 241 if ( i++ >= n ) { 242 break; 243 } 244 isPrime = p.isProbablePrime(63); 245 if ( !isPrime ) { 246 System.out.println("not prime = " + p); 247 return false; 248 } 249 } 250 return true; 251 } 252 253 254 /** 255 * toString. 256 */ 257 @Override 258 public String toString() { 259 return val.toString(); 260 } 261 262 263 /** 264 * size of current list. 265 */ 266 public int size() { 267 return val.size(); 268 } 269 270 271 /** 272 * get prime at index i. 273 */ 274 public java.math.BigInteger get(int i) { 275 java.math.BigInteger p; 276 if ( i < size() ) { 277 p = val.get(i); 278 } else { 279 p = last.nextProbablePrime(); 280 val.add( p ); 281 last = p; 282 } 283 return p; 284 } 285 286 287 /** 288 * Iterator. 289 */ 290 public Iterator<java.math.BigInteger> iterator() { 291 return new Iterator<java.math.BigInteger>() { 292 int index = -1; 293 public boolean hasNext() { 294 return true; 295 } 296 public void remove() { 297 throw new UnsupportedOperationException("remove not implemented"); 298 } 299 public java.math.BigInteger next() { 300 index++; 301 return get(index); 302 } 303 }; 304 } 305 306 }