blob: 17c58bce98122e874a1c3aefa3765cc494b36e58 [file] [log] [blame]
darcy32db4492009-01-26 19:49:26 -08001/*
bpb28090952013-06-19 08:59:39 -07002 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
darcy32db4492009-01-26 19:49:26 -08003 * 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 *
ohair2283b9d2010-05-25 15:58:33 -070019 * 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.
darcy32db4492009-01-26 19:49:26 -080022 */
23
24/*
25 * @test
bpb28090952013-06-19 08:59:39 -070026 * @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946
darcy32db4492009-01-26 19:49:26 -080027 * @summary tests methods in BigInteger
28 * @run main/timeout=400 BigIntegerTest
29 * @author madbot
30 */
31
bpb28090952013-06-19 08:59:39 -070032import java.io.File;
33import java.io.FileInputStream;
34import java.io.FileOutputStream;
35import java.io.ObjectInputStream;
36import java.io.ObjectOutputStream;
darcy32db4492009-01-26 19:49:26 -080037import java.math.BigInteger;
bpb28090952013-06-19 08:59:39 -070038import java.util.Random;
darcy32db4492009-01-26 19:49:26 -080039
40/**
41 * This is a simple test class created to ensure that the results
42 * generated by BigInteger adhere to certain identities. Passing
43 * this test is a strong assurance that the BigInteger operations
44 * are working correctly.
45 *
46 * Three arguments may be specified which give the number of
47 * decimal digits you desire in the three batches of test numbers.
48 *
49 * The tests are performed on arrays of random numbers which are
50 * generated by a Random class as well as special cases which
51 * throw in boundary numbers such as 0, 1, maximum sized, etc.
52 *
53 */
54public class BigIntegerTest {
bpb28090952013-06-19 08:59:39 -070055 //
56 // Bit large number thresholds based on the int thresholds
57 // defined in BigInteger itself:
58 //
59 // KARATSUBA_THRESHOLD = 50 ints = 1600 bits
60 // TOOM_COOK_THRESHOLD = 75 ints = 2400 bits
61 // KARATSUBA_SQUARE_THRESHOLD = 90 ints = 2880 bits
62 // TOOM_COOK_SQUARE_THRESHOLD = 140 ints = 4480 bits
63 //
bpb3c584672013-06-20 12:15:24 -070064 // SCHOENHAGE_BASE_CONVERSION_THRESHOLD = 8 ints = 256 bits
65 //
bpb28090952013-06-19 08:59:39 -070066 static final int BITS_KARATSUBA = 1600;
67 static final int BITS_TOOM_COOK = 2400;
68 static final int BITS_KARATSUBA_SQUARE = 2880;
69 static final int BITS_TOOM_COOK_SQUARE = 4480;
bpb3c584672013-06-20 12:15:24 -070070 static final int BITS_SCHOENHAGE_BASE = 256;
bpb28090952013-06-19 08:59:39 -070071
72 static final int ORDER_SMALL = 60;
73 static final int ORDER_MEDIUM = 100;
74 // #bits for testing Karatsuba and Burnikel-Ziegler
75 static final int ORDER_KARATSUBA = 1800;
76 // #bits for testing Toom-Cook
77 static final int ORDER_TOOM_COOK = 3000;
78 // #bits for testing Karatsuba squaring
79 static final int ORDER_KARATSUBA_SQUARE = 3200;
80 // #bits for testing Toom-Cook squaring
81 static final int ORDER_TOOM_COOK_SQUARE = 4600;
82
darcy32db4492009-01-26 19:49:26 -080083 static Random rnd = new Random();
84 static int size = 1000; // numbers per batch
85 static boolean failure = false;
86
bpb28090952013-06-19 08:59:39 -070087 public static void pow(int order) {
darcy32db4492009-01-26 19:49:26 -080088 int failCount1 = 0;
89
90 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -070091 // Test identity x^power == x*x*x ... *x
92 int power = rnd.nextInt(6) + 2;
93 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -080094 BigInteger y = x.pow(power);
95 BigInteger z = x;
96
97 for (int j=1; j<power; j++)
98 z = z.multiply(x);
99
100 if (!y.equals(z))
101 failCount1++;
102 }
bpb28090952013-06-19 08:59:39 -0700103 report("pow for " + order + " bits", failCount1);
darcy32db4492009-01-26 19:49:26 -0800104 }
105
bpb28090952013-06-19 08:59:39 -0700106 public static void square(int order) {
107 int failCount1 = 0;
108
109 for (int i=0; i<size; i++) {
110 // Test identity x^2 == x*x
111 BigInteger x = fetchNumber(order);
112 BigInteger xx = x.multiply(x);
113 BigInteger x2 = x.pow(2);
114
115 if (!x2.equals(xx))
116 failCount1++;
117 }
118 report("square for " + order + " bits", failCount1);
119 }
120
121 public static void arithmetic(int order) {
darcy32db4492009-01-26 19:49:26 -0800122 int failCount = 0;
123
124 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700125 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800126 while(x.compareTo(BigInteger.ZERO) != 1)
bpb28090952013-06-19 08:59:39 -0700127 x = fetchNumber(order);
128 BigInteger y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800129 while(x.compareTo(y) == -1)
bpb28090952013-06-19 08:59:39 -0700130 y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800131 if (y.equals(BigInteger.ZERO))
132 y = y.add(BigInteger.ONE);
133
bpb28090952013-06-19 08:59:39 -0700134 // Test identity ((x/y))*y + x%y - x == 0
135 // using separate divide() and remainder()
darcy32db4492009-01-26 19:49:26 -0800136 BigInteger baz = x.divide(y);
137 baz = baz.multiply(y);
138 baz = baz.add(x.remainder(y));
139 baz = baz.subtract(x);
140 if (!baz.equals(BigInteger.ZERO))
141 failCount++;
142 }
bpb28090952013-06-19 08:59:39 -0700143 report("Arithmetic I for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800144
145 failCount = 0;
146 for (int i=0; i<100; i++) {
bpb28090952013-06-19 08:59:39 -0700147 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800148 while(x.compareTo(BigInteger.ZERO) != 1)
bpb28090952013-06-19 08:59:39 -0700149 x = fetchNumber(order);
150 BigInteger y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800151 while(x.compareTo(y) == -1)
bpb28090952013-06-19 08:59:39 -0700152 y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800153 if (y.equals(BigInteger.ZERO))
154 y = y.add(BigInteger.ONE);
155
bpb28090952013-06-19 08:59:39 -0700156 // Test identity ((x/y))*y + x%y - x == 0
157 // using divideAndRemainder()
darcy32db4492009-01-26 19:49:26 -0800158 BigInteger baz[] = x.divideAndRemainder(y);
159 baz[0] = baz[0].multiply(y);
160 baz[0] = baz[0].add(baz[1]);
161 baz[0] = baz[0].subtract(x);
162 if (!baz[0].equals(BigInteger.ZERO))
163 failCount++;
164 }
bpb28090952013-06-19 08:59:39 -0700165 report("Arithmetic II for " + order + " bits", failCount);
166 }
167
168 /**
169 * Sanity test for Karatsuba and 3-way Toom-Cook multiplication.
170 * For each of the Karatsuba and 3-way Toom-Cook multiplication thresholds,
171 * construct two factors each with a mag array one element shorter than the
172 * threshold, and with the most significant bit set and the rest of the bits
173 * random. Each of these numbers will therefore be below the threshold but
174 * if shifted left be above the threshold. Call the numbers 'u' and 'v' and
175 * define random shifts 'a' and 'b' in the range [1,32]. Then we have the
176 * identity
177 * <pre>
178 * (u << a)*(v << b) = (u*v) << (a + b)
179 * </pre>
180 * For Karatsuba multiplication, the right hand expression will be evaluated
181 * using the standard naive algorithm, and the left hand expression using
182 * the Karatsuba algorithm. For 3-way Toom-Cook multiplication, the right
183 * hand expression will be evaluated using Karatsuba multiplication, and the
184 * left hand expression using 3-way Toom-Cook multiplication.
185 */
186 public static void multiplyLarge() {
187 int failCount = 0;
188
189 BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA - 32 - 1);
190 for (int i=0; i<size; i++) {
191 BigInteger x = fetchNumber(BITS_KARATSUBA - 32 - 1);
192 BigInteger u = base.add(x);
193 int a = 1 + rnd.nextInt(31);
194 BigInteger w = u.shiftLeft(a);
195
196 BigInteger y = fetchNumber(BITS_KARATSUBA - 32 - 1);
197 BigInteger v = base.add(y);
198 int b = 1 + rnd.nextInt(32);
199 BigInteger z = v.shiftLeft(b);
200
201 BigInteger multiplyResult = u.multiply(v).shiftLeft(a + b);
202 BigInteger karatsubaMultiplyResult = w.multiply(z);
203
204 if (!multiplyResult.equals(karatsubaMultiplyResult)) {
205 failCount++;
206 }
207 }
208
209 report("multiplyLarge Karatsuba", failCount);
210
211 failCount = 0;
212 base = base.shiftLeft(BITS_TOOM_COOK - BITS_KARATSUBA);
213 for (int i=0; i<size; i++) {
214 BigInteger x = fetchNumber(BITS_TOOM_COOK - 32 - 1);
215 BigInteger u = base.add(x);
216 BigInteger u2 = u.shiftLeft(1);
217 BigInteger y = fetchNumber(BITS_TOOM_COOK - 32 - 1);
218 BigInteger v = base.add(y);
219 BigInteger v2 = v.shiftLeft(1);
220
221 BigInteger multiplyResult = u.multiply(v).shiftLeft(2);
222 BigInteger toomCookMultiplyResult = u2.multiply(v2);
223
224 if (!multiplyResult.equals(toomCookMultiplyResult)) {
225 failCount++;
226 }
227 }
228
229 report("multiplyLarge Toom-Cook", failCount);
230 }
231
232 /**
233 * Sanity test for Karatsuba and 3-way Toom-Cook squaring.
234 * This test is analogous to {@link AbstractMethodError#multiplyLarge}
235 * with both factors being equal. The squaring methods will not be tested
236 * unless the <code>bigInteger.multiply(bigInteger)</code> tests whether
237 * the parameter is the same instance on which the method is being invoked
238 * and calls <code>square()</code> accordingly.
239 */
240 public static void squareLarge() {
241 int failCount = 0;
242
243 BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA_SQUARE - 32 - 1);
244 for (int i=0; i<size; i++) {
245 BigInteger x = fetchNumber(BITS_KARATSUBA_SQUARE - 32 - 1);
246 BigInteger u = base.add(x);
247 int a = 1 + rnd.nextInt(31);
248 BigInteger w = u.shiftLeft(a);
249
250 BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
251 BigInteger karatsubaSquareResult = w.multiply(w);
252
253 if (!squareResult.equals(karatsubaSquareResult)) {
254 failCount++;
255 }
256 }
257
258 report("squareLarge Karatsuba", failCount);
259
260 failCount = 0;
261 base = base.shiftLeft(BITS_TOOM_COOK_SQUARE - BITS_KARATSUBA_SQUARE);
262 for (int i=0; i<size; i++) {
263 BigInteger x = fetchNumber(BITS_TOOM_COOK_SQUARE - 32 - 1);
264 BigInteger u = base.add(x);
265 int a = 1 + rnd.nextInt(31);
266 BigInteger w = u.shiftLeft(a);
267
268 BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
269 BigInteger toomCookSquareResult = w.multiply(w);
270
271 if (!squareResult.equals(toomCookSquareResult)) {
272 failCount++;
273 }
274 }
275
276 report("squareLarge Toom-Cook", failCount);
darcy32db4492009-01-26 19:49:26 -0800277 }
278
279 public static void bitCount() {
280 int failCount = 0;
281
282 for (int i=0; i<size*10; i++) {
283 int x = rnd.nextInt();
284 BigInteger bigX = BigInteger.valueOf((long)x);
285 int bit = (x < 0 ? 0 : 1);
286 int tmp = x, bitCount = 0;
287 for (int j=0; j<32; j++) {
288 bitCount += ((tmp & 1) == bit ? 1 : 0);
289 tmp >>= 1;
290 }
291
292 if (bigX.bitCount() != bitCount) {
293 //System.err.println(x+": "+bitCount+", "+bigX.bitCount());
294 failCount++;
295 }
296 }
297 report("Bit Count", failCount);
298 }
299
300 public static void bitLength() {
301 int failCount = 0;
302
303 for (int i=0; i<size*10; i++) {
304 int x = rnd.nextInt();
305 BigInteger bigX = BigInteger.valueOf((long)x);
306 int signBit = (x < 0 ? 0x80000000 : 0);
307 int tmp = x, bitLength, j;
308 for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++)
309 tmp <<= 1;
310 bitLength = 32 - j;
311
312 if (bigX.bitLength() != bitLength) {
313 //System.err.println(x+": "+bitLength+", "+bigX.bitLength());
314 failCount++;
315 }
316 }
317
318 report("BitLength", failCount);
319 }
320
bpb28090952013-06-19 08:59:39 -0700321 public static void bitOps(int order) {
darcy32db4492009-01-26 19:49:26 -0800322 int failCount1 = 0, failCount2 = 0, failCount3 = 0;
323
324 for (int i=0; i<size*5; i++) {
bpb28090952013-06-19 08:59:39 -0700325 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800326 BigInteger y;
327
bpb28090952013-06-19 08:59:39 -0700328 // Test setBit and clearBit (and testBit)
darcy32db4492009-01-26 19:49:26 -0800329 if (x.signum() < 0) {
330 y = BigInteger.valueOf(-1);
331 for (int j=0; j<x.bitLength(); j++)
332 if (!x.testBit(j))
333 y = y.clearBit(j);
334 } else {
335 y = BigInteger.ZERO;
336 for (int j=0; j<x.bitLength(); j++)
337 if (x.testBit(j))
338 y = y.setBit(j);
339 }
340 if (!x.equals(y))
341 failCount1++;
342
bpb28090952013-06-19 08:59:39 -0700343 // Test flipBit (and testBit)
darcy32db4492009-01-26 19:49:26 -0800344 y = BigInteger.valueOf(x.signum()<0 ? -1 : 0);
345 for (int j=0; j<x.bitLength(); j++)
346 if (x.signum()<0 ^ x.testBit(j))
347 y = y.flipBit(j);
348 if (!x.equals(y))
349 failCount2++;
350 }
bpb28090952013-06-19 08:59:39 -0700351 report("clearBit/testBit for " + order + " bits", failCount1);
352 report("flipBit/testBit for " + order + " bits", failCount2);
darcy32db4492009-01-26 19:49:26 -0800353
354 for (int i=0; i<size*5; i++) {
bpb28090952013-06-19 08:59:39 -0700355 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800356
bpb28090952013-06-19 08:59:39 -0700357 // Test getLowestSetBit()
darcy32db4492009-01-26 19:49:26 -0800358 int k = x.getLowestSetBit();
359 if (x.signum() == 0) {
360 if (k != -1)
361 failCount3++;
362 } else {
363 BigInteger z = x.and(x.negate());
364 int j;
365 for (j=0; j<z.bitLength() && !z.testBit(j); j++)
366 ;
367 if (k != j)
368 failCount3++;
369 }
370 }
bpb28090952013-06-19 08:59:39 -0700371 report("getLowestSetBit for " + order + " bits", failCount3);
darcy32db4492009-01-26 19:49:26 -0800372 }
373
bpb28090952013-06-19 08:59:39 -0700374 public static void bitwise(int order) {
darcy32db4492009-01-26 19:49:26 -0800375
bpb28090952013-06-19 08:59:39 -0700376 // Test identity x^y == x|y &~ x&y
darcy32db4492009-01-26 19:49:26 -0800377 int failCount = 0;
378 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700379 BigInteger x = fetchNumber(order);
380 BigInteger y = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800381 BigInteger z = x.xor(y);
382 BigInteger w = x.or(y).andNot(x.and(y));
383 if (!z.equals(w))
384 failCount++;
385 }
bpb28090952013-06-19 08:59:39 -0700386 report("Logic (^ | & ~) for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800387
bpb28090952013-06-19 08:59:39 -0700388 // Test identity x &~ y == ~(~x | y)
darcy32db4492009-01-26 19:49:26 -0800389 failCount = 0;
390 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700391 BigInteger x = fetchNumber(order);
392 BigInteger y = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800393 BigInteger z = x.andNot(y);
394 BigInteger w = x.not().or(y).not();
395 if (!z.equals(w))
396 failCount++;
397 }
bpb28090952013-06-19 08:59:39 -0700398 report("Logic (&~ | ~) for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800399 }
400
bpb28090952013-06-19 08:59:39 -0700401 public static void shift(int order) {
darcy32db4492009-01-26 19:49:26 -0800402 int failCount1 = 0;
403 int failCount2 = 0;
404 int failCount3 = 0;
405
406 for (int i=0; i<100; i++) {
bpb28090952013-06-19 08:59:39 -0700407 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800408 int n = Math.abs(rnd.nextInt()%200);
409
410 if (!x.shiftLeft(n).equals
411 (x.multiply(BigInteger.valueOf(2L).pow(n))))
412 failCount1++;
413
414 BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n));
415 BigInteger z = (x.signum()<0 && y[1].signum()!=0
416 ? y[0].subtract(BigInteger.ONE)
417 : y[0]);
418
419 BigInteger b = x.shiftRight(n);
420
421 if (!b.equals(z)) {
422 System.err.println("Input is "+x.toString(2));
423 System.err.println("shift is "+n);
424
425 System.err.println("Divided "+z.toString(2));
426 System.err.println("Shifted is "+b.toString(2));
427 if (b.toString().equals(z.toString()))
428 System.err.println("Houston, we have a problem.");
429 failCount2++;
430 }
431
432 if (!x.shiftLeft(n).shiftRight(n).equals(x))
433 failCount3++;
434 }
bpb28090952013-06-19 08:59:39 -0700435 report("baz shiftLeft for " + order + " bits", failCount1);
436 report("baz shiftRight for " + order + " bits", failCount2);
437 report("baz shiftLeft/Right for " + order + " bits", failCount3);
darcy32db4492009-01-26 19:49:26 -0800438 }
439
bpb28090952013-06-19 08:59:39 -0700440 public static void divideAndRemainder(int order) {
darcy32db4492009-01-26 19:49:26 -0800441 int failCount1 = 0;
442
443 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700444 BigInteger x = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800445 while(x.compareTo(BigInteger.valueOf(3L)) != 1)
bpb28090952013-06-19 08:59:39 -0700446 x = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800447 BigInteger z = x.divide(BigInteger.valueOf(2L));
448 BigInteger y[] = x.divideAndRemainder(x);
449 if (!y[0].equals(BigInteger.ONE)) {
450 failCount1++;
451 System.err.println("fail1 x :"+x);
452 System.err.println(" y :"+y);
453 }
454 else if (!y[1].equals(BigInteger.ZERO)) {
455 failCount1++;
456 System.err.println("fail2 x :"+x);
457 System.err.println(" y :"+y);
458 }
459
460 y = x.divideAndRemainder(z);
461 if (!y[0].equals(BigInteger.valueOf(2))) {
462 failCount1++;
463 System.err.println("fail3 x :"+x);
464 System.err.println(" y :"+y);
465 }
466 }
bpb28090952013-06-19 08:59:39 -0700467 report("divideAndRemainder for " + order + " bits", failCount1);
darcy32db4492009-01-26 19:49:26 -0800468 }
469
470 public static void stringConv() {
471 int failCount = 0;
472
bpb3c584672013-06-20 12:15:24 -0700473 // Generic string conversion.
darcy32db4492009-01-26 19:49:26 -0800474 for (int i=0; i<100; i++) {
475 byte xBytes[] = new byte[Math.abs(rnd.nextInt())%100+1];
476 rnd.nextBytes(xBytes);
477 BigInteger x = new BigInteger(xBytes);
478
bpb3c584672013-06-20 12:15:24 -0700479 for (int radix=Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) {
darcy32db4492009-01-26 19:49:26 -0800480 String result = x.toString(radix);
481 BigInteger test = new BigInteger(result, radix);
482 if (!test.equals(x)) {
483 failCount++;
484 System.err.println("BigInteger toString: "+x);
485 System.err.println("Test: "+test);
486 System.err.println(radix);
487 }
488 }
489 }
bpb3c584672013-06-20 12:15:24 -0700490
491 // String conversion straddling the Schoenhage algorithm crossover
492 // threshold, and at twice and four times the threshold.
493 for (int k = 0; k <= 2; k++) {
494 int factor = 1 << k;
495 int upper = factor * BITS_SCHOENHAGE_BASE + 33;
496 int lower = upper - 35;
497
498 for (int bits = upper; bits >= lower; bits--) {
499 for (int i = 0; i < 50; i++) {
500 BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, rnd));
501
502 for (int radix = Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) {
503 String result = x.toString(radix);
504 BigInteger test = new BigInteger(result, radix);
505 if (!test.equals(x)) {
506 failCount++;
507 System.err.println("BigInteger toString: " + x);
508 System.err.println("Test: " + test);
509 System.err.println(radix);
510 }
511 }
512 }
513 }
514 }
515
darcy32db4492009-01-26 19:49:26 -0800516 report("String Conversion", failCount);
517 }
518
bpb28090952013-06-19 08:59:39 -0700519 public static void byteArrayConv(int order) {
darcy32db4492009-01-26 19:49:26 -0800520 int failCount = 0;
521
522 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700523 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800524 while (x.equals(BigInteger.ZERO))
bpb28090952013-06-19 08:59:39 -0700525 x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800526 BigInteger y = new BigInteger(x.toByteArray());
527 if (!x.equals(y)) {
528 failCount++;
529 System.err.println("orig is "+x);
530 System.err.println("new is "+y);
531 }
532 }
bpb28090952013-06-19 08:59:39 -0700533 report("Array Conversion for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800534 }
535
bpb28090952013-06-19 08:59:39 -0700536 public static void modInv(int order) {
darcy32db4492009-01-26 19:49:26 -0800537 int failCount = 0, successCount = 0, nonInvCount = 0;
538
539 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700540 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800541 while(x.equals(BigInteger.ZERO))
bpb28090952013-06-19 08:59:39 -0700542 x = fetchNumber(order);
543 BigInteger m = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800544 while(m.compareTo(BigInteger.ONE) != 1)
bpb28090952013-06-19 08:59:39 -0700545 m = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800546
547 try {
548 BigInteger inv = x.modInverse(m);
549 BigInteger prod = inv.multiply(x).remainder(m);
550
551 if (prod.signum() == -1)
552 prod = prod.add(m);
553
554 if (prod.equals(BigInteger.ONE))
555 successCount++;
556 else
557 failCount++;
558 } catch(ArithmeticException e) {
559 nonInvCount++;
560 }
561 }
bpb28090952013-06-19 08:59:39 -0700562 report("Modular Inverse for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800563 }
564
bpb28090952013-06-19 08:59:39 -0700565 public static void modExp(int order1, int order2) {
darcy32db4492009-01-26 19:49:26 -0800566 int failCount = 0;
567
568 for (int i=0; i<size/10; i++) {
569 BigInteger m = fetchNumber(order1).abs();
570 while(m.compareTo(BigInteger.ONE) != 1)
571 m = fetchNumber(order1).abs();
572 BigInteger base = fetchNumber(order2);
573 BigInteger exp = fetchNumber(8).abs();
574
575 BigInteger z = base.modPow(exp, m);
576 BigInteger w = base.pow(exp.intValue()).mod(m);
577 if (!z.equals(w)) {
578 System.err.println("z is "+z);
579 System.err.println("w is "+w);
580 System.err.println("mod is "+m);
581 System.err.println("base is "+base);
582 System.err.println("exp is "+exp);
583 failCount++;
584 }
585 }
bpb28090952013-06-19 08:59:39 -0700586 report("Exponentiation I for " + order1 + " and " +
587 order2 + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800588 }
589
590 // This test is based on Fermat's theorem
591 // which is not ideal because base must not be multiple of modulus
592 // and modulus must be a prime or pseudoprime (Carmichael number)
bpb28090952013-06-19 08:59:39 -0700593 public static void modExp2(int order) {
darcy32db4492009-01-26 19:49:26 -0800594 int failCount = 0;
595
596 for (int i=0; i<10; i++) {
597 BigInteger m = new BigInteger(100, 5, rnd);
598 while(m.compareTo(BigInteger.ONE) != 1)
599 m = new BigInteger(100, 5, rnd);
600 BigInteger exp = m.subtract(BigInteger.ONE);
bpb28090952013-06-19 08:59:39 -0700601 BigInteger base = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800602 while(base.compareTo(m) != -1)
bpb28090952013-06-19 08:59:39 -0700603 base = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800604 while(base.equals(BigInteger.ZERO))
bpb28090952013-06-19 08:59:39 -0700605 base = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800606
607 BigInteger one = base.modPow(exp, m);
608 if (!one.equals(BigInteger.ONE)) {
609 System.err.println("m is "+m);
610 System.err.println("base is "+base);
611 System.err.println("exp is "+exp);
612 failCount++;
613 }
614 }
bpb28090952013-06-19 08:59:39 -0700615 report("Exponentiation II for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800616 }
617
618 private static final int[] mersenne_powers = {
619 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937,
620 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433,
621 1257787, 1398269, 2976221, 3021377, 6972593, 13466917 };
622
623 private static final long[] carmichaels = {
624 561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,
625 62745,63973,75361,101101,115921,126217,162401,172081,188461,252601,
626 278545,294409,314821,334153,340561,399001,410041,449065,488881,512461,
627 225593397919L };
628
629 // Note: testing the larger ones takes too long.
630 private static final int NUM_MERSENNES_TO_TEST = 7;
631 // Note: this constant used for computed Carmichaels, not the array above
632 private static final int NUM_CARMICHAELS_TO_TEST = 5;
633
634 private static final String[] customer_primes = {
635 "120000000000000000000000000000000019",
636 "633825300114114700748351603131",
637 "1461501637330902918203684832716283019651637554291",
638 "779626057591079617852292862756047675913380626199",
639 "857591696176672809403750477631580323575362410491",
640 "910409242326391377348778281801166102059139832131",
641 "929857869954035706722619989283358182285540127919",
642 "961301750640481375785983980066592002055764391999",
643 "1267617700951005189537696547196156120148404630231",
644 "1326015641149969955786344600146607663033642528339" };
645
646 private static final BigInteger ZERO = BigInteger.ZERO;
647 private static final BigInteger ONE = BigInteger.ONE;
648 private static final BigInteger TWO = new BigInteger("2");
649 private static final BigInteger SIX = new BigInteger("6");
650 private static final BigInteger TWELVE = new BigInteger("12");
651 private static final BigInteger EIGHTEEN = new BigInteger("18");
652
653 public static void prime() {
654 BigInteger p1, p2, c1;
655 int failCount = 0;
656
657 // Test consistency
658 for(int i=0; i<10; i++) {
659 p1 = BigInteger.probablePrime(100, rnd);
660 if (!p1.isProbablePrime(100)) {
661 System.err.println("Consistency "+p1.toString(16));
662 failCount++;
663 }
664 }
665
666 // Test some known Mersenne primes (2^n)-1
667 // The array holds the exponents, not the numbers being tested
668 for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) {
669 p1 = new BigInteger("2");
670 p1 = p1.pow(mersenne_powers[i]);
671 p1 = p1.subtract(BigInteger.ONE);
672 if (!p1.isProbablePrime(100)) {
673 System.err.println("Mersenne prime "+i+ " failed.");
674 failCount++;
675 }
676 }
677
678 // Test some primes reported by customers as failing in the past
679 for (int i=0; i<customer_primes.length; i++) {
680 p1 = new BigInteger(customer_primes[i]);
681 if (!p1.isProbablePrime(100)) {
682 System.err.println("Customer prime "+i+ " failed.");
683 failCount++;
684 }
685 }
686
687 // Test some known Carmichael numbers.
688 for (int i=0; i<carmichaels.length; i++) {
689 c1 = BigInteger.valueOf(carmichaels[i]);
690 if(c1.isProbablePrime(100)) {
691 System.err.println("Carmichael "+i+ " reported as prime.");
692 failCount++;
693 }
694 }
695
696 // Test some computed Carmichael numbers.
697 // Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if
698 // each of the factors is prime
699 int found = 0;
700 BigInteger f1 = new BigInteger(40, 100, rnd);
701 while (found < NUM_CARMICHAELS_TO_TEST) {
702 BigInteger k = null;
703 BigInteger f2, f3;
704 f1 = f1.nextProbablePrime();
705 BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX);
706 if (result[1].equals(ZERO)) {
707 k = result[0];
708 f2 = k.multiply(TWELVE).add(ONE);
709 if (f2.isProbablePrime(100)) {
710 f3 = k.multiply(EIGHTEEN).add(ONE);
711 if (f3.isProbablePrime(100)) {
712 c1 = f1.multiply(f2).multiply(f3);
713 if (c1.isProbablePrime(100)) {
714 System.err.println("Computed Carmichael "
715 +c1.toString(16));
716 failCount++;
717 }
718 found++;
719 }
720 }
721 }
722 f1 = f1.add(TWO);
723 }
724
725 // Test some composites that are products of 2 primes
726 for (int i=0; i<50; i++) {
727 p1 = BigInteger.probablePrime(100, rnd);
728 p2 = BigInteger.probablePrime(100, rnd);
729 c1 = p1.multiply(p2);
730 if (c1.isProbablePrime(100)) {
731 System.err.println("Composite failed "+c1.toString(16));
732 failCount++;
733 }
734 }
735
736 for (int i=0; i<4; i++) {
737 p1 = BigInteger.probablePrime(600, rnd);
738 p2 = BigInteger.probablePrime(600, rnd);
739 c1 = p1.multiply(p2);
740 if (c1.isProbablePrime(100)) {
741 System.err.println("Composite failed "+c1.toString(16));
742 failCount++;
743 }
744 }
745
746 report("Prime", failCount);
747 }
748
749 private static final long[] primesTo100 = {
750 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
751 };
752
753 private static final long[] aPrimeSequence = {
754 1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L,
755 1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L,
756 1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L,
757 1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L,
758 1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L,
759 1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L,
760 1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L,
761 1999999853L, 1999999861L, 1999999871L, 1999999873
762 };
763
764 public static void nextProbablePrime() throws Exception {
765 int failCount = 0;
766 BigInteger p1, p2, p3;
767 p1 = p2 = p3 = ZERO;
768
769 // First test nextProbablePrime on the low range starting at zero
770 for (int i=0; i<primesTo100.length; i++) {
771 p1 = p1.nextProbablePrime();
772 if (p1.longValue() != primesTo100[i]) {
773 System.err.println("low range primes failed");
774 System.err.println("p1 is "+p1);
775 System.err.println("expected "+primesTo100[i]);
776 failCount++;
777 }
778 }
779
780 // Test nextProbablePrime on a relatively small, known prime sequence
781 p1 = BigInteger.valueOf(aPrimeSequence[0]);
782 for (int i=1; i<aPrimeSequence.length; i++) {
783 p1 = p1.nextProbablePrime();
784 if (p1.longValue() != aPrimeSequence[i]) {
785 System.err.println("prime sequence failed");
786 failCount++;
787 }
788 }
789
790 // Next, pick some large primes, use nextProbablePrime to find the
791 // next one, and make sure there are no primes in between
792 for (int i=0; i<100; i+=10) {
793 p1 = BigInteger.probablePrime(50 + i, rnd);
794 p2 = p1.add(ONE);
795 p3 = p1.nextProbablePrime();
796 while(p2.compareTo(p3) < 0) {
797 if (p2.isProbablePrime(100)){
798 System.err.println("nextProbablePrime failed");
799 System.err.println("along range "+p1.toString(16));
800 System.err.println("to "+p3.toString(16));
801 failCount++;
802 break;
803 }
804 p2 = p2.add(ONE);
805 }
806 }
807
808 report("nextProbablePrime", failCount);
809 }
810
811 public static void serialize() throws Exception {
812 int failCount = 0;
813
814 String bitPatterns[] = {
815 "ffffffff00000000ffffffff00000000ffffffff00000000",
816 "ffffffffffffffffffffffff000000000000000000000000",
817 "ffffffff0000000000000000000000000000000000000000",
818 "10000000ffffffffffffffffffffffffffffffffffffffff",
819 "100000000000000000000000000000000000000000000000",
820 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
821 "-ffffffff00000000ffffffff00000000ffffffff00000000",
822 "-ffffffffffffffffffffffff000000000000000000000000",
823 "-ffffffff0000000000000000000000000000000000000000",
824 "-10000000ffffffffffffffffffffffffffffffffffffffff",
825 "-100000000000000000000000000000000000000000000000",
826 "-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
827 };
828
829 for(int i = 0; i < bitPatterns.length; i++) {
830 BigInteger b1 = new BigInteger(bitPatterns[i], 16);
darcye5dbfef2009-12-22 21:48:19 -0800831 BigInteger b2 = null;
darcy32db4492009-01-26 19:49:26 -0800832
833 File f = new File("serialtest");
smarks1dba3592011-02-22 15:34:17 -0800834
835 try (FileOutputStream fos = new FileOutputStream(f)) {
836 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
darcye5dbfef2009-12-22 21:48:19 -0800837 oos.writeObject(b1);
838 oos.flush();
darcye5dbfef2009-12-22 21:48:19 -0800839 }
darcy32db4492009-01-26 19:49:26 -0800840
smarks1dba3592011-02-22 15:34:17 -0800841 try (FileInputStream fis = new FileInputStream(f);
842 ObjectInputStream ois = new ObjectInputStream(fis))
843 {
844 b2 = (BigInteger)ois.readObject();
darcye5dbfef2009-12-22 21:48:19 -0800845 }
846
847 if (!b1.equals(b2) ||
848 !b1.equals(b1.or(b2))) {
849 failCount++;
850 System.err.println("Serialized failed for hex " +
851 b1.toString(16));
852 }
darcy32db4492009-01-26 19:49:26 -0800853 }
854 f.delete();
855 }
856
857 for(int i=0; i<10; i++) {
858 BigInteger b1 = fetchNumber(rnd.nextInt(100));
darcye5dbfef2009-12-22 21:48:19 -0800859 BigInteger b2 = null;
darcy32db4492009-01-26 19:49:26 -0800860 File f = new File("serialtest");
smarks1dba3592011-02-22 15:34:17 -0800861 try (FileOutputStream fos = new FileOutputStream(f)) {
862 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
darcye5dbfef2009-12-22 21:48:19 -0800863 oos.writeObject(b1);
864 oos.flush();
darcye5dbfef2009-12-22 21:48:19 -0800865 }
866
smarks1dba3592011-02-22 15:34:17 -0800867 try (FileInputStream fis = new FileInputStream(f);
868 ObjectInputStream ois = new ObjectInputStream(fis))
869 {
870 b2 = (BigInteger)ois.readObject();
darcye5dbfef2009-12-22 21:48:19 -0800871 }
darcye5dbfef2009-12-22 21:48:19 -0800872 }
darcy32db4492009-01-26 19:49:26 -0800873
874 if (!b1.equals(b2) ||
875 !b1.equals(b1.or(b2)))
876 failCount++;
877 f.delete();
878 }
879
880 report("Serialize", failCount);
881 }
882
883 /**
884 * Main to interpret arguments and run several tests.
885 *
886 * Up to three arguments may be given to specify the size of BigIntegers
887 * used for call parameters 1, 2, and 3. The size is interpreted as
888 * the maximum number of decimal digits that the parameters will have.
889 *
890 */
891 public static void main(String[] args) throws Exception {
892
bpb28090952013-06-19 08:59:39 -0700893 // Some variables for sizing test numbers in bits
894 int order1 = ORDER_MEDIUM;
895 int order2 = ORDER_SMALL;
896 int order3 = ORDER_KARATSUBA;
897 int order4 = ORDER_TOOM_COOK;
898
darcy32db4492009-01-26 19:49:26 -0800899 if (args.length >0)
900 order1 = (int)((Integer.parseInt(args[0]))* 3.333);
901 if (args.length >1)
902 order2 = (int)((Integer.parseInt(args[1]))* 3.333);
903 if (args.length >2)
904 order3 = (int)((Integer.parseInt(args[2]))* 3.333);
bpb28090952013-06-19 08:59:39 -0700905 if (args.length >3)
906 order4 = (int)((Integer.parseInt(args[3]))* 3.333);
darcy32db4492009-01-26 19:49:26 -0800907
908 prime();
909 nextProbablePrime();
910
bpb28090952013-06-19 08:59:39 -0700911 arithmetic(order1); // small numbers
912 arithmetic(order3); // Karatsuba / Burnikel-Ziegler range
913 arithmetic(order4); // Toom-Cook range
914
915 divideAndRemainder(order1); // small numbers
916 divideAndRemainder(order3); // Karatsuba / Burnikel-Ziegler range
917 divideAndRemainder(order4); // Toom-Cook range
918
919 pow(order1);
920 pow(order3);
921 pow(order4);
922
923 square(ORDER_MEDIUM);
924 square(ORDER_KARATSUBA_SQUARE);
925 square(ORDER_TOOM_COOK_SQUARE);
darcy32db4492009-01-26 19:49:26 -0800926
927 bitCount();
928 bitLength();
bpb28090952013-06-19 08:59:39 -0700929 bitOps(order1);
930 bitwise(order1);
darcy32db4492009-01-26 19:49:26 -0800931
bpb28090952013-06-19 08:59:39 -0700932 shift(order1);
darcy32db4492009-01-26 19:49:26 -0800933
bpb28090952013-06-19 08:59:39 -0700934 byteArrayConv(order1);
darcy32db4492009-01-26 19:49:26 -0800935
bpb28090952013-06-19 08:59:39 -0700936 modInv(order1); // small numbers
937 modInv(order3); // Karatsuba / Burnikel-Ziegler range
938 modInv(order4); // Toom-Cook range
939
940 modExp(order1, order2);
941 modExp2(order1);
darcy32db4492009-01-26 19:49:26 -0800942
943 stringConv();
944 serialize();
945
bpb28090952013-06-19 08:59:39 -0700946 multiplyLarge();
947 squareLarge();
948
darcy32db4492009-01-26 19:49:26 -0800949 if (failure)
950 throw new RuntimeException("Failure in BigIntegerTest.");
951 }
952
953 /*
954 * Get a random or boundary-case number. This is designed to provide
955 * a lot of numbers that will find failure points, such as max sized
956 * numbers, empty BigIntegers, etc.
957 *
958 * If order is less than 2, order is changed to 2.
959 */
960 private static BigInteger fetchNumber(int order) {
961 boolean negative = rnd.nextBoolean();
bpb28090952013-06-19 08:59:39 -0700962 int numType = rnd.nextInt(7);
darcy32db4492009-01-26 19:49:26 -0800963 BigInteger result = null;
964 if (order < 2) order = 2;
965
966 switch (numType) {
967 case 0: // Empty
968 result = BigInteger.ZERO;
969 break;
970
971 case 1: // One
972 result = BigInteger.ONE;
973 break;
974
975 case 2: // All bits set in number
976 int numBytes = (order+7)/8;
977 byte[] fullBits = new byte[numBytes];
978 for(int i=0; i<numBytes; i++)
979 fullBits[i] = (byte)0xff;
980 int excessBits = 8*numBytes - order;
981 fullBits[0] &= (1 << (8-excessBits)) - 1;
982 result = new BigInteger(1, fullBits);
983 break;
984
985 case 3: // One bit in number
986 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
987 break;
988
989 case 4: // Random bit density
990 int iterations = rnd.nextInt(order-1);
991 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
992 for(int i=0; i<iterations; i++) {
993 BigInteger temp = BigInteger.ONE.shiftLeft(
994 rnd.nextInt(order));
995 result = result.or(temp);
996 }
997 break;
bpb28090952013-06-19 08:59:39 -0700998 case 5: // Runs of consecutive ones and zeros
999 result = ZERO;
1000 int remaining = order;
1001 int bit = rnd.nextInt(2);
1002 while (remaining > 0) {
1003 int runLength = Math.min(remaining, rnd.nextInt(order));
1004 result = result.shiftLeft(runLength);
1005 if (bit > 0)
1006 result = result.add(ONE.shiftLeft(runLength).subtract(ONE));
1007 remaining -= runLength;
1008 bit = 1 - bit;
1009 }
1010 break;
darcy32db4492009-01-26 19:49:26 -08001011
1012 default: // random bits
1013 result = new BigInteger(order, rnd);
1014 }
1015
1016 if (negative)
1017 result = result.negate();
1018
1019 return result;
1020 }
1021
1022 static void report(String testName, int failCount) {
1023 System.err.println(testName+": " +
1024 (failCount==0 ? "Passed":"Failed("+failCount+")"));
1025 if (failCount > 0)
1026 failure = true;
1027 }
1028}