author | ohair |
Wed, 06 Apr 2011 22:06:11 -0700 | |
changeset 9035 | 1255eb81cc2f |
parent 8543 | e5ec12a932da |
child 18286 | b38489d5aadf |
permissions | -rw-r--r-- |
1826 | 1 |
/* |
9035
1255eb81cc2f
7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents:
8543
diff
changeset
|
2 |
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. |
1826 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
5506 | 19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 |
* or visit www.oracle.com if you need additional information or have any |
|
21 |
* questions. |
|
1826 | 22 |
*/ |
23 |
||
24 |
/* |
|
25 |
* @test |
|
26 |
* @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 |
|
27 |
* @summary tests methods in BigInteger |
|
28 |
* @run main/timeout=400 BigIntegerTest |
|
29 |
* @author madbot |
|
30 |
*/ |
|
31 |
||
32 |
import java.util.Random; |
|
33 |
import java.math.BigInteger; |
|
34 |
import java.io.*; |
|
35 |
||
36 |
/** |
|
37 |
* This is a simple test class created to ensure that the results |
|
38 |
* generated by BigInteger adhere to certain identities. Passing |
|
39 |
* this test is a strong assurance that the BigInteger operations |
|
40 |
* are working correctly. |
|
41 |
* |
|
42 |
* Three arguments may be specified which give the number of |
|
43 |
* decimal digits you desire in the three batches of test numbers. |
|
44 |
* |
|
45 |
* The tests are performed on arrays of random numbers which are |
|
46 |
* generated by a Random class as well as special cases which |
|
47 |
* throw in boundary numbers such as 0, 1, maximum sized, etc. |
|
48 |
* |
|
49 |
*/ |
|
50 |
public class BigIntegerTest { |
|
51 |
static Random rnd = new Random(); |
|
52 |
static int size = 1000; // numbers per batch |
|
53 |
static boolean failure = false; |
|
54 |
||
55 |
// Some variables for sizing test numbers in bits |
|
56 |
private static int order1 = 100; |
|
57 |
private static int order2 = 60; |
|
58 |
private static int order3 = 30; |
|
59 |
||
60 |
public static void pow() { |
|
61 |
int failCount1 = 0; |
|
62 |
||
63 |
for (int i=0; i<size; i++) { |
|
64 |
int power = rnd.nextInt(6) +2; |
|
65 |
BigInteger x = fetchNumber(order1); |
|
66 |
BigInteger y = x.pow(power); |
|
67 |
BigInteger z = x; |
|
68 |
||
69 |
for (int j=1; j<power; j++) |
|
70 |
z = z.multiply(x); |
|
71 |
||
72 |
if (!y.equals(z)) |
|
73 |
failCount1++; |
|
74 |
} |
|
75 |
report("pow", failCount1); |
|
76 |
} |
|
77 |
||
78 |
public static void arithmetic() { |
|
79 |
int failCount = 0; |
|
80 |
||
81 |
for (int i=0; i<size; i++) { |
|
82 |
BigInteger x = fetchNumber(order1); |
|
83 |
while(x.compareTo(BigInteger.ZERO) != 1) |
|
84 |
x = fetchNumber(order1); |
|
85 |
BigInteger y = fetchNumber(order1/2); |
|
86 |
while(x.compareTo(y) == -1) |
|
87 |
y = fetchNumber(order1/2); |
|
88 |
if (y.equals(BigInteger.ZERO)) |
|
89 |
y = y.add(BigInteger.ONE); |
|
90 |
||
91 |
BigInteger baz = x.divide(y); |
|
92 |
baz = baz.multiply(y); |
|
93 |
baz = baz.add(x.remainder(y)); |
|
94 |
baz = baz.subtract(x); |
|
95 |
if (!baz.equals(BigInteger.ZERO)) |
|
96 |
failCount++; |
|
97 |
} |
|
98 |
report("Arithmetic I", failCount); |
|
99 |
||
100 |
failCount = 0; |
|
101 |
for (int i=0; i<100; i++) { |
|
102 |
BigInteger x = fetchNumber(order1); |
|
103 |
while(x.compareTo(BigInteger.ZERO) != 1) |
|
104 |
x = fetchNumber(order1); |
|
105 |
BigInteger y = fetchNumber(order1/2); |
|
106 |
while(x.compareTo(y) == -1) |
|
107 |
y = fetchNumber(order1/2); |
|
108 |
if (y.equals(BigInteger.ZERO)) |
|
109 |
y = y.add(BigInteger.ONE); |
|
110 |
||
111 |
BigInteger baz[] = x.divideAndRemainder(y); |
|
112 |
baz[0] = baz[0].multiply(y); |
|
113 |
baz[0] = baz[0].add(baz[1]); |
|
114 |
baz[0] = baz[0].subtract(x); |
|
115 |
if (!baz[0].equals(BigInteger.ZERO)) |
|
116 |
failCount++; |
|
117 |
} |
|
118 |
report("Arithmetic II", failCount); |
|
119 |
} |
|
120 |
||
121 |
public static void bitCount() { |
|
122 |
int failCount = 0; |
|
123 |
||
124 |
for (int i=0; i<size*10; i++) { |
|
125 |
int x = rnd.nextInt(); |
|
126 |
BigInteger bigX = BigInteger.valueOf((long)x); |
|
127 |
int bit = (x < 0 ? 0 : 1); |
|
128 |
int tmp = x, bitCount = 0; |
|
129 |
for (int j=0; j<32; j++) { |
|
130 |
bitCount += ((tmp & 1) == bit ? 1 : 0); |
|
131 |
tmp >>= 1; |
|
132 |
} |
|
133 |
||
134 |
if (bigX.bitCount() != bitCount) { |
|
135 |
//System.err.println(x+": "+bitCount+", "+bigX.bitCount()); |
|
136 |
failCount++; |
|
137 |
} |
|
138 |
} |
|
139 |
report("Bit Count", failCount); |
|
140 |
} |
|
141 |
||
142 |
public static void bitLength() { |
|
143 |
int failCount = 0; |
|
144 |
||
145 |
for (int i=0; i<size*10; i++) { |
|
146 |
int x = rnd.nextInt(); |
|
147 |
BigInteger bigX = BigInteger.valueOf((long)x); |
|
148 |
int signBit = (x < 0 ? 0x80000000 : 0); |
|
149 |
int tmp = x, bitLength, j; |
|
150 |
for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++) |
|
151 |
tmp <<= 1; |
|
152 |
bitLength = 32 - j; |
|
153 |
||
154 |
if (bigX.bitLength() != bitLength) { |
|
155 |
//System.err.println(x+": "+bitLength+", "+bigX.bitLength()); |
|
156 |
failCount++; |
|
157 |
} |
|
158 |
} |
|
159 |
||
160 |
report("BitLength", failCount); |
|
161 |
} |
|
162 |
||
163 |
public static void bitOps() { |
|
164 |
int failCount1 = 0, failCount2 = 0, failCount3 = 0; |
|
165 |
||
166 |
for (int i=0; i<size*5; i++) { |
|
167 |
BigInteger x = fetchNumber(order1); |
|
168 |
BigInteger y; |
|
169 |
||
170 |
/* Test setBit and clearBit (and testBit) */ |
|
171 |
if (x.signum() < 0) { |
|
172 |
y = BigInteger.valueOf(-1); |
|
173 |
for (int j=0; j<x.bitLength(); j++) |
|
174 |
if (!x.testBit(j)) |
|
175 |
y = y.clearBit(j); |
|
176 |
} else { |
|
177 |
y = BigInteger.ZERO; |
|
178 |
for (int j=0; j<x.bitLength(); j++) |
|
179 |
if (x.testBit(j)) |
|
180 |
y = y.setBit(j); |
|
181 |
} |
|
182 |
if (!x.equals(y)) |
|
183 |
failCount1++; |
|
184 |
||
185 |
/* Test flipBit (and testBit) */ |
|
186 |
y = BigInteger.valueOf(x.signum()<0 ? -1 : 0); |
|
187 |
for (int j=0; j<x.bitLength(); j++) |
|
188 |
if (x.signum()<0 ^ x.testBit(j)) |
|
189 |
y = y.flipBit(j); |
|
190 |
if (!x.equals(y)) |
|
191 |
failCount2++; |
|
192 |
} |
|
193 |
report("clearBit/testBit", failCount1); |
|
194 |
report("flipBit/testBit", failCount2); |
|
195 |
||
196 |
for (int i=0; i<size*5; i++) { |
|
197 |
BigInteger x = fetchNumber(order1); |
|
198 |
||
199 |
/* Test getLowestSetBit() */ |
|
200 |
int k = x.getLowestSetBit(); |
|
201 |
if (x.signum() == 0) { |
|
202 |
if (k != -1) |
|
203 |
failCount3++; |
|
204 |
} else { |
|
205 |
BigInteger z = x.and(x.negate()); |
|
206 |
int j; |
|
207 |
for (j=0; j<z.bitLength() && !z.testBit(j); j++) |
|
208 |
; |
|
209 |
if (k != j) |
|
210 |
failCount3++; |
|
211 |
} |
|
212 |
} |
|
213 |
report("getLowestSetBit", failCount3); |
|
214 |
} |
|
215 |
||
216 |
public static void bitwise() { |
|
217 |
||
218 |
/* Test identity x^y == x|y &~ x&y */ |
|
219 |
int failCount = 0; |
|
220 |
for (int i=0; i<size; i++) { |
|
221 |
BigInteger x = fetchNumber(order1); |
|
222 |
BigInteger y = fetchNumber(order1); |
|
223 |
BigInteger z = x.xor(y); |
|
224 |
BigInteger w = x.or(y).andNot(x.and(y)); |
|
225 |
if (!z.equals(w)) |
|
226 |
failCount++; |
|
227 |
} |
|
228 |
report("Logic (^ | & ~)", failCount); |
|
229 |
||
230 |
/* Test identity x &~ y == ~(~x | y) */ |
|
231 |
failCount = 0; |
|
232 |
for (int i=0; i<size; i++) { |
|
233 |
BigInteger x = fetchNumber(order1); |
|
234 |
BigInteger y = fetchNumber(order1); |
|
235 |
BigInteger z = x.andNot(y); |
|
236 |
BigInteger w = x.not().or(y).not(); |
|
237 |
if (!z.equals(w)) |
|
238 |
failCount++; |
|
239 |
} |
|
240 |
report("Logic (&~ | ~)", failCount); |
|
241 |
} |
|
242 |
||
243 |
public static void shift() { |
|
244 |
int failCount1 = 0; |
|
245 |
int failCount2 = 0; |
|
246 |
int failCount3 = 0; |
|
247 |
||
248 |
for (int i=0; i<100; i++) { |
|
249 |
BigInteger x = fetchNumber(order1); |
|
250 |
int n = Math.abs(rnd.nextInt()%200); |
|
251 |
||
252 |
if (!x.shiftLeft(n).equals |
|
253 |
(x.multiply(BigInteger.valueOf(2L).pow(n)))) |
|
254 |
failCount1++; |
|
255 |
||
256 |
BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n)); |
|
257 |
BigInteger z = (x.signum()<0 && y[1].signum()!=0 |
|
258 |
? y[0].subtract(BigInteger.ONE) |
|
259 |
: y[0]); |
|
260 |
||
261 |
BigInteger b = x.shiftRight(n); |
|
262 |
||
263 |
if (!b.equals(z)) { |
|
264 |
System.err.println("Input is "+x.toString(2)); |
|
265 |
System.err.println("shift is "+n); |
|
266 |
||
267 |
System.err.println("Divided "+z.toString(2)); |
|
268 |
System.err.println("Shifted is "+b.toString(2)); |
|
269 |
if (b.toString().equals(z.toString())) |
|
270 |
System.err.println("Houston, we have a problem."); |
|
271 |
failCount2++; |
|
272 |
} |
|
273 |
||
274 |
if (!x.shiftLeft(n).shiftRight(n).equals(x)) |
|
275 |
failCount3++; |
|
276 |
} |
|
277 |
report("baz shiftLeft", failCount1); |
|
278 |
report("baz shiftRight", failCount2); |
|
279 |
report("baz shiftLeft/Right", failCount3); |
|
280 |
} |
|
281 |
||
282 |
public static void divideAndRemainder() { |
|
283 |
int failCount1 = 0; |
|
284 |
||
285 |
for (int i=0; i<size; i++) { |
|
286 |
BigInteger x = fetchNumber(order1).abs(); |
|
287 |
while(x.compareTo(BigInteger.valueOf(3L)) != 1) |
|
288 |
x = fetchNumber(order1).abs(); |
|
289 |
BigInteger z = x.divide(BigInteger.valueOf(2L)); |
|
290 |
BigInteger y[] = x.divideAndRemainder(x); |
|
291 |
if (!y[0].equals(BigInteger.ONE)) { |
|
292 |
failCount1++; |
|
293 |
System.err.println("fail1 x :"+x); |
|
294 |
System.err.println(" y :"+y); |
|
295 |
} |
|
296 |
else if (!y[1].equals(BigInteger.ZERO)) { |
|
297 |
failCount1++; |
|
298 |
System.err.println("fail2 x :"+x); |
|
299 |
System.err.println(" y :"+y); |
|
300 |
} |
|
301 |
||
302 |
y = x.divideAndRemainder(z); |
|
303 |
if (!y[0].equals(BigInteger.valueOf(2))) { |
|
304 |
failCount1++; |
|
305 |
System.err.println("fail3 x :"+x); |
|
306 |
System.err.println(" y :"+y); |
|
307 |
} |
|
308 |
} |
|
309 |
report("divideAndRemainder I", failCount1); |
|
310 |
} |
|
311 |
||
312 |
public static void stringConv() { |
|
313 |
int failCount = 0; |
|
314 |
||
315 |
for (int i=0; i<100; i++) { |
|
316 |
byte xBytes[] = new byte[Math.abs(rnd.nextInt())%100+1]; |
|
317 |
rnd.nextBytes(xBytes); |
|
318 |
BigInteger x = new BigInteger(xBytes); |
|
319 |
||
320 |
for (int radix=2; radix < 37; radix++) { |
|
321 |
String result = x.toString(radix); |
|
322 |
BigInteger test = new BigInteger(result, radix); |
|
323 |
if (!test.equals(x)) { |
|
324 |
failCount++; |
|
325 |
System.err.println("BigInteger toString: "+x); |
|
326 |
System.err.println("Test: "+test); |
|
327 |
System.err.println(radix); |
|
328 |
} |
|
329 |
} |
|
330 |
} |
|
331 |
report("String Conversion", failCount); |
|
332 |
} |
|
333 |
||
334 |
public static void byteArrayConv() { |
|
335 |
int failCount = 0; |
|
336 |
||
337 |
for (int i=0; i<size; i++) { |
|
338 |
BigInteger x = fetchNumber(order1); |
|
339 |
while (x.equals(BigInteger.ZERO)) |
|
340 |
x = fetchNumber(order1); |
|
341 |
BigInteger y = new BigInteger(x.toByteArray()); |
|
342 |
if (!x.equals(y)) { |
|
343 |
failCount++; |
|
344 |
System.err.println("orig is "+x); |
|
345 |
System.err.println("new is "+y); |
|
346 |
} |
|
347 |
} |
|
348 |
report("Array Conversion", failCount); |
|
349 |
} |
|
350 |
||
351 |
public static void modInv() { |
|
352 |
int failCount = 0, successCount = 0, nonInvCount = 0; |
|
353 |
||
354 |
for (int i=0; i<size; i++) { |
|
355 |
BigInteger x = fetchNumber(order1); |
|
356 |
while(x.equals(BigInteger.ZERO)) |
|
357 |
x = fetchNumber(order1); |
|
358 |
BigInteger m = fetchNumber(order1).abs(); |
|
359 |
while(m.compareTo(BigInteger.ONE) != 1) |
|
360 |
m = fetchNumber(order1).abs(); |
|
361 |
||
362 |
try { |
|
363 |
BigInteger inv = x.modInverse(m); |
|
364 |
BigInteger prod = inv.multiply(x).remainder(m); |
|
365 |
||
366 |
if (prod.signum() == -1) |
|
367 |
prod = prod.add(m); |
|
368 |
||
369 |
if (prod.equals(BigInteger.ONE)) |
|
370 |
successCount++; |
|
371 |
else |
|
372 |
failCount++; |
|
373 |
} catch(ArithmeticException e) { |
|
374 |
nonInvCount++; |
|
375 |
} |
|
376 |
} |
|
377 |
report("Modular Inverse", failCount); |
|
378 |
} |
|
379 |
||
380 |
public static void modExp() { |
|
381 |
int failCount = 0; |
|
382 |
||
383 |
for (int i=0; i<size/10; i++) { |
|
384 |
BigInteger m = fetchNumber(order1).abs(); |
|
385 |
while(m.compareTo(BigInteger.ONE) != 1) |
|
386 |
m = fetchNumber(order1).abs(); |
|
387 |
BigInteger base = fetchNumber(order2); |
|
388 |
BigInteger exp = fetchNumber(8).abs(); |
|
389 |
||
390 |
BigInteger z = base.modPow(exp, m); |
|
391 |
BigInteger w = base.pow(exp.intValue()).mod(m); |
|
392 |
if (!z.equals(w)) { |
|
393 |
System.err.println("z is "+z); |
|
394 |
System.err.println("w is "+w); |
|
395 |
System.err.println("mod is "+m); |
|
396 |
System.err.println("base is "+base); |
|
397 |
System.err.println("exp is "+exp); |
|
398 |
failCount++; |
|
399 |
} |
|
400 |
} |
|
401 |
report("Exponentiation I", failCount); |
|
402 |
} |
|
403 |
||
404 |
// This test is based on Fermat's theorem |
|
405 |
// which is not ideal because base must not be multiple of modulus |
|
406 |
// and modulus must be a prime or pseudoprime (Carmichael number) |
|
407 |
public static void modExp2() { |
|
408 |
int failCount = 0; |
|
409 |
||
410 |
for (int i=0; i<10; i++) { |
|
411 |
BigInteger m = new BigInteger(100, 5, rnd); |
|
412 |
while(m.compareTo(BigInteger.ONE) != 1) |
|
413 |
m = new BigInteger(100, 5, rnd); |
|
414 |
BigInteger exp = m.subtract(BigInteger.ONE); |
|
415 |
BigInteger base = fetchNumber(order1).abs(); |
|
416 |
while(base.compareTo(m) != -1) |
|
417 |
base = fetchNumber(order1).abs(); |
|
418 |
while(base.equals(BigInteger.ZERO)) |
|
419 |
base = fetchNumber(order1).abs(); |
|
420 |
||
421 |
BigInteger one = base.modPow(exp, m); |
|
422 |
if (!one.equals(BigInteger.ONE)) { |
|
423 |
System.err.println("m is "+m); |
|
424 |
System.err.println("base is "+base); |
|
425 |
System.err.println("exp is "+exp); |
|
426 |
failCount++; |
|
427 |
} |
|
428 |
} |
|
429 |
report("Exponentiation II", failCount); |
|
430 |
} |
|
431 |
||
432 |
private static final int[] mersenne_powers = { |
|
433 |
521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937, |
|
434 |
21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433, |
|
435 |
1257787, 1398269, 2976221, 3021377, 6972593, 13466917 }; |
|
436 |
||
437 |
private static final long[] carmichaels = { |
|
438 |
561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633, |
|
439 |
62745,63973,75361,101101,115921,126217,162401,172081,188461,252601, |
|
440 |
278545,294409,314821,334153,340561,399001,410041,449065,488881,512461, |
|
441 |
225593397919L }; |
|
442 |
||
443 |
// Note: testing the larger ones takes too long. |
|
444 |
private static final int NUM_MERSENNES_TO_TEST = 7; |
|
445 |
// Note: this constant used for computed Carmichaels, not the array above |
|
446 |
private static final int NUM_CARMICHAELS_TO_TEST = 5; |
|
447 |
||
448 |
private static final String[] customer_primes = { |
|
449 |
"120000000000000000000000000000000019", |
|
450 |
"633825300114114700748351603131", |
|
451 |
"1461501637330902918203684832716283019651637554291", |
|
452 |
"779626057591079617852292862756047675913380626199", |
|
453 |
"857591696176672809403750477631580323575362410491", |
|
454 |
"910409242326391377348778281801166102059139832131", |
|
455 |
"929857869954035706722619989283358182285540127919", |
|
456 |
"961301750640481375785983980066592002055764391999", |
|
457 |
"1267617700951005189537696547196156120148404630231", |
|
458 |
"1326015641149969955786344600146607663033642528339" }; |
|
459 |
||
460 |
private static final BigInteger ZERO = BigInteger.ZERO; |
|
461 |
private static final BigInteger ONE = BigInteger.ONE; |
|
462 |
private static final BigInteger TWO = new BigInteger("2"); |
|
463 |
private static final BigInteger SIX = new BigInteger("6"); |
|
464 |
private static final BigInteger TWELVE = new BigInteger("12"); |
|
465 |
private static final BigInteger EIGHTEEN = new BigInteger("18"); |
|
466 |
||
467 |
public static void prime() { |
|
468 |
BigInteger p1, p2, c1; |
|
469 |
int failCount = 0; |
|
470 |
||
471 |
// Test consistency |
|
472 |
for(int i=0; i<10; i++) { |
|
473 |
p1 = BigInteger.probablePrime(100, rnd); |
|
474 |
if (!p1.isProbablePrime(100)) { |
|
475 |
System.err.println("Consistency "+p1.toString(16)); |
|
476 |
failCount++; |
|
477 |
} |
|
478 |
} |
|
479 |
||
480 |
// Test some known Mersenne primes (2^n)-1 |
|
481 |
// The array holds the exponents, not the numbers being tested |
|
482 |
for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) { |
|
483 |
p1 = new BigInteger("2"); |
|
484 |
p1 = p1.pow(mersenne_powers[i]); |
|
485 |
p1 = p1.subtract(BigInteger.ONE); |
|
486 |
if (!p1.isProbablePrime(100)) { |
|
487 |
System.err.println("Mersenne prime "+i+ " failed."); |
|
488 |
failCount++; |
|
489 |
} |
|
490 |
} |
|
491 |
||
492 |
// Test some primes reported by customers as failing in the past |
|
493 |
for (int i=0; i<customer_primes.length; i++) { |
|
494 |
p1 = new BigInteger(customer_primes[i]); |
|
495 |
if (!p1.isProbablePrime(100)) { |
|
496 |
System.err.println("Customer prime "+i+ " failed."); |
|
497 |
failCount++; |
|
498 |
} |
|
499 |
} |
|
500 |
||
501 |
// Test some known Carmichael numbers. |
|
502 |
for (int i=0; i<carmichaels.length; i++) { |
|
503 |
c1 = BigInteger.valueOf(carmichaels[i]); |
|
504 |
if(c1.isProbablePrime(100)) { |
|
505 |
System.err.println("Carmichael "+i+ " reported as prime."); |
|
506 |
failCount++; |
|
507 |
} |
|
508 |
} |
|
509 |
||
510 |
// Test some computed Carmichael numbers. |
|
511 |
// Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if |
|
512 |
// each of the factors is prime |
|
513 |
int found = 0; |
|
514 |
BigInteger f1 = new BigInteger(40, 100, rnd); |
|
515 |
while (found < NUM_CARMICHAELS_TO_TEST) { |
|
516 |
BigInteger k = null; |
|
517 |
BigInteger f2, f3; |
|
518 |
f1 = f1.nextProbablePrime(); |
|
519 |
BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX); |
|
520 |
if (result[1].equals(ZERO)) { |
|
521 |
k = result[0]; |
|
522 |
f2 = k.multiply(TWELVE).add(ONE); |
|
523 |
if (f2.isProbablePrime(100)) { |
|
524 |
f3 = k.multiply(EIGHTEEN).add(ONE); |
|
525 |
if (f3.isProbablePrime(100)) { |
|
526 |
c1 = f1.multiply(f2).multiply(f3); |
|
527 |
if (c1.isProbablePrime(100)) { |
|
528 |
System.err.println("Computed Carmichael " |
|
529 |
+c1.toString(16)); |
|
530 |
failCount++; |
|
531 |
} |
|
532 |
found++; |
|
533 |
} |
|
534 |
} |
|
535 |
} |
|
536 |
f1 = f1.add(TWO); |
|
537 |
} |
|
538 |
||
539 |
// Test some composites that are products of 2 primes |
|
540 |
for (int i=0; i<50; i++) { |
|
541 |
p1 = BigInteger.probablePrime(100, rnd); |
|
542 |
p2 = BigInteger.probablePrime(100, rnd); |
|
543 |
c1 = p1.multiply(p2); |
|
544 |
if (c1.isProbablePrime(100)) { |
|
545 |
System.err.println("Composite failed "+c1.toString(16)); |
|
546 |
failCount++; |
|
547 |
} |
|
548 |
} |
|
549 |
||
550 |
for (int i=0; i<4; i++) { |
|
551 |
p1 = BigInteger.probablePrime(600, rnd); |
|
552 |
p2 = BigInteger.probablePrime(600, rnd); |
|
553 |
c1 = p1.multiply(p2); |
|
554 |
if (c1.isProbablePrime(100)) { |
|
555 |
System.err.println("Composite failed "+c1.toString(16)); |
|
556 |
failCount++; |
|
557 |
} |
|
558 |
} |
|
559 |
||
560 |
report("Prime", failCount); |
|
561 |
} |
|
562 |
||
563 |
private static final long[] primesTo100 = { |
|
564 |
2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97 |
|
565 |
}; |
|
566 |
||
567 |
private static final long[] aPrimeSequence = { |
|
568 |
1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L, |
|
569 |
1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L, |
|
570 |
1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L, |
|
571 |
1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L, |
|
572 |
1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L, |
|
573 |
1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L, |
|
574 |
1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L, |
|
575 |
1999999853L, 1999999861L, 1999999871L, 1999999873 |
|
576 |
}; |
|
577 |
||
578 |
public static void nextProbablePrime() throws Exception { |
|
579 |
int failCount = 0; |
|
580 |
BigInteger p1, p2, p3; |
|
581 |
p1 = p2 = p3 = ZERO; |
|
582 |
||
583 |
// First test nextProbablePrime on the low range starting at zero |
|
584 |
for (int i=0; i<primesTo100.length; i++) { |
|
585 |
p1 = p1.nextProbablePrime(); |
|
586 |
if (p1.longValue() != primesTo100[i]) { |
|
587 |
System.err.println("low range primes failed"); |
|
588 |
System.err.println("p1 is "+p1); |
|
589 |
System.err.println("expected "+primesTo100[i]); |
|
590 |
failCount++; |
|
591 |
} |
|
592 |
} |
|
593 |
||
594 |
// Test nextProbablePrime on a relatively small, known prime sequence |
|
595 |
p1 = BigInteger.valueOf(aPrimeSequence[0]); |
|
596 |
for (int i=1; i<aPrimeSequence.length; i++) { |
|
597 |
p1 = p1.nextProbablePrime(); |
|
598 |
if (p1.longValue() != aPrimeSequence[i]) { |
|
599 |
System.err.println("prime sequence failed"); |
|
600 |
failCount++; |
|
601 |
} |
|
602 |
} |
|
603 |
||
604 |
// Next, pick some large primes, use nextProbablePrime to find the |
|
605 |
// next one, and make sure there are no primes in between |
|
606 |
for (int i=0; i<100; i+=10) { |
|
607 |
p1 = BigInteger.probablePrime(50 + i, rnd); |
|
608 |
p2 = p1.add(ONE); |
|
609 |
p3 = p1.nextProbablePrime(); |
|
610 |
while(p2.compareTo(p3) < 0) { |
|
611 |
if (p2.isProbablePrime(100)){ |
|
612 |
System.err.println("nextProbablePrime failed"); |
|
613 |
System.err.println("along range "+p1.toString(16)); |
|
614 |
System.err.println("to "+p3.toString(16)); |
|
615 |
failCount++; |
|
616 |
break; |
|
617 |
} |
|
618 |
p2 = p2.add(ONE); |
|
619 |
} |
|
620 |
} |
|
621 |
||
622 |
report("nextProbablePrime", failCount); |
|
623 |
} |
|
624 |
||
625 |
public static void serialize() throws Exception { |
|
626 |
int failCount = 0; |
|
627 |
||
628 |
String bitPatterns[] = { |
|
629 |
"ffffffff00000000ffffffff00000000ffffffff00000000", |
|
630 |
"ffffffffffffffffffffffff000000000000000000000000", |
|
631 |
"ffffffff0000000000000000000000000000000000000000", |
|
632 |
"10000000ffffffffffffffffffffffffffffffffffffffff", |
|
633 |
"100000000000000000000000000000000000000000000000", |
|
634 |
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", |
|
635 |
"-ffffffff00000000ffffffff00000000ffffffff00000000", |
|
636 |
"-ffffffffffffffffffffffff000000000000000000000000", |
|
637 |
"-ffffffff0000000000000000000000000000000000000000", |
|
638 |
"-10000000ffffffffffffffffffffffffffffffffffffffff", |
|
639 |
"-100000000000000000000000000000000000000000000000", |
|
640 |
"-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" |
|
641 |
}; |
|
642 |
||
643 |
for(int i = 0; i < bitPatterns.length; i++) { |
|
644 |
BigInteger b1 = new BigInteger(bitPatterns[i], 16); |
|
4527
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
645 |
BigInteger b2 = null; |
1826 | 646 |
|
647 |
File f = new File("serialtest"); |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
648 |
|
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
649 |
try (FileOutputStream fos = new FileOutputStream(f)) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
650 |
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) { |
4527
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
651 |
oos.writeObject(b1); |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
652 |
oos.flush(); |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
653 |
} |
1826 | 654 |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
655 |
try (FileInputStream fis = new FileInputStream(f); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
656 |
ObjectInputStream ois = new ObjectInputStream(fis)) |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
657 |
{ |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
658 |
b2 = (BigInteger)ois.readObject(); |
4527
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
659 |
} |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
660 |
|
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
661 |
if (!b1.equals(b2) || |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
662 |
!b1.equals(b1.or(b2))) { |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
663 |
failCount++; |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
664 |
System.err.println("Serialized failed for hex " + |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
665 |
b1.toString(16)); |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
666 |
} |
1826 | 667 |
} |
668 |
f.delete(); |
|
669 |
} |
|
670 |
||
671 |
for(int i=0; i<10; i++) { |
|
672 |
BigInteger b1 = fetchNumber(rnd.nextInt(100)); |
|
4527
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
673 |
BigInteger b2 = null; |
1826 | 674 |
File f = new File("serialtest"); |
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
675 |
try (FileOutputStream fos = new FileOutputStream(f)) { |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
676 |
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) { |
4527
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
677 |
oos.writeObject(b1); |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
678 |
oos.flush(); |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
679 |
} |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
680 |
|
8543
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
681 |
try (FileInputStream fis = new FileInputStream(f); |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
682 |
ObjectInputStream ois = new ObjectInputStream(fis)) |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
683 |
{ |
e5ec12a932da
7021209: convert lang, math, util to use try-with-resources
smarks
parents:
5506
diff
changeset
|
684 |
b2 = (BigInteger)ois.readObject(); |
4527
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
685 |
} |
f95d12f08613
6908541: Bad resource management in java/math/BigInteger/BigIntegerTest.java
darcy
parents:
1826
diff
changeset
|
686 |
} |
1826 | 687 |
|
688 |
if (!b1.equals(b2) || |
|
689 |
!b1.equals(b1.or(b2))) |
|
690 |
failCount++; |
|
691 |
f.delete(); |
|
692 |
} |
|
693 |
||
694 |
report("Serialize", failCount); |
|
695 |
} |
|
696 |
||
697 |
/** |
|
698 |
* Main to interpret arguments and run several tests. |
|
699 |
* |
|
700 |
* Up to three arguments may be given to specify the size of BigIntegers |
|
701 |
* used for call parameters 1, 2, and 3. The size is interpreted as |
|
702 |
* the maximum number of decimal digits that the parameters will have. |
|
703 |
* |
|
704 |
*/ |
|
705 |
public static void main(String[] args) throws Exception { |
|
706 |
||
707 |
if (args.length >0) |
|
708 |
order1 = (int)((Integer.parseInt(args[0]))* 3.333); |
|
709 |
if (args.length >1) |
|
710 |
order2 = (int)((Integer.parseInt(args[1]))* 3.333); |
|
711 |
if (args.length >2) |
|
712 |
order3 = (int)((Integer.parseInt(args[2]))* 3.333); |
|
713 |
||
714 |
prime(); |
|
715 |
nextProbablePrime(); |
|
716 |
||
717 |
arithmetic(); |
|
718 |
divideAndRemainder(); |
|
719 |
pow(); |
|
720 |
||
721 |
bitCount(); |
|
722 |
bitLength(); |
|
723 |
bitOps(); |
|
724 |
bitwise(); |
|
725 |
||
726 |
shift(); |
|
727 |
||
728 |
byteArrayConv(); |
|
729 |
||
730 |
modInv(); |
|
731 |
modExp(); |
|
732 |
modExp2(); |
|
733 |
||
734 |
stringConv(); |
|
735 |
serialize(); |
|
736 |
||
737 |
if (failure) |
|
738 |
throw new RuntimeException("Failure in BigIntegerTest."); |
|
739 |
} |
|
740 |
||
741 |
/* |
|
742 |
* Get a random or boundary-case number. This is designed to provide |
|
743 |
* a lot of numbers that will find failure points, such as max sized |
|
744 |
* numbers, empty BigIntegers, etc. |
|
745 |
* |
|
746 |
* If order is less than 2, order is changed to 2. |
|
747 |
*/ |
|
748 |
private static BigInteger fetchNumber(int order) { |
|
749 |
boolean negative = rnd.nextBoolean(); |
|
750 |
int numType = rnd.nextInt(6); |
|
751 |
BigInteger result = null; |
|
752 |
if (order < 2) order = 2; |
|
753 |
||
754 |
switch (numType) { |
|
755 |
case 0: // Empty |
|
756 |
result = BigInteger.ZERO; |
|
757 |
break; |
|
758 |
||
759 |
case 1: // One |
|
760 |
result = BigInteger.ONE; |
|
761 |
break; |
|
762 |
||
763 |
case 2: // All bits set in number |
|
764 |
int numBytes = (order+7)/8; |
|
765 |
byte[] fullBits = new byte[numBytes]; |
|
766 |
for(int i=0; i<numBytes; i++) |
|
767 |
fullBits[i] = (byte)0xff; |
|
768 |
int excessBits = 8*numBytes - order; |
|
769 |
fullBits[0] &= (1 << (8-excessBits)) - 1; |
|
770 |
result = new BigInteger(1, fullBits); |
|
771 |
break; |
|
772 |
||
773 |
case 3: // One bit in number |
|
774 |
result = BigInteger.ONE.shiftLeft(rnd.nextInt(order)); |
|
775 |
break; |
|
776 |
||
777 |
case 4: // Random bit density |
|
778 |
int iterations = rnd.nextInt(order-1); |
|
779 |
result = BigInteger.ONE.shiftLeft(rnd.nextInt(order)); |
|
780 |
for(int i=0; i<iterations; i++) { |
|
781 |
BigInteger temp = BigInteger.ONE.shiftLeft( |
|
782 |
rnd.nextInt(order)); |
|
783 |
result = result.or(temp); |
|
784 |
} |
|
785 |
break; |
|
786 |
||
787 |
default: // random bits |
|
788 |
result = new BigInteger(order, rnd); |
|
789 |
} |
|
790 |
||
791 |
if (negative) |
|
792 |
result = result.negate(); |
|
793 |
||
794 |
return result; |
|
795 |
} |
|
796 |
||
797 |
static void report(String testName, int failCount) { |
|
798 |
System.err.println(testName+": " + |
|
799 |
(failCount==0 ? "Passed":"Failed("+failCount+")")); |
|
800 |
if (failCount > 0) |
|
801 |
failure = true; |
|
802 |
} |
|
803 |
} |