blob: 4522d4440bfac9748ce114a689dc3121f72422a8 [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 //
64 static final int BITS_KARATSUBA = 1600;
65 static final int BITS_TOOM_COOK = 2400;
66 static final int BITS_KARATSUBA_SQUARE = 2880;
67 static final int BITS_TOOM_COOK_SQUARE = 4480;
68
69 static final int ORDER_SMALL = 60;
70 static final int ORDER_MEDIUM = 100;
71 // #bits for testing Karatsuba and Burnikel-Ziegler
72 static final int ORDER_KARATSUBA = 1800;
73 // #bits for testing Toom-Cook
74 static final int ORDER_TOOM_COOK = 3000;
75 // #bits for testing Karatsuba squaring
76 static final int ORDER_KARATSUBA_SQUARE = 3200;
77 // #bits for testing Toom-Cook squaring
78 static final int ORDER_TOOM_COOK_SQUARE = 4600;
79
darcy32db4492009-01-26 19:49:26 -080080 static Random rnd = new Random();
81 static int size = 1000; // numbers per batch
82 static boolean failure = false;
83
bpb28090952013-06-19 08:59:39 -070084 public static void pow(int order) {
darcy32db4492009-01-26 19:49:26 -080085 int failCount1 = 0;
86
87 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -070088 // Test identity x^power == x*x*x ... *x
89 int power = rnd.nextInt(6) + 2;
90 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -080091 BigInteger y = x.pow(power);
92 BigInteger z = x;
93
94 for (int j=1; j<power; j++)
95 z = z.multiply(x);
96
97 if (!y.equals(z))
98 failCount1++;
99 }
bpb28090952013-06-19 08:59:39 -0700100 report("pow for " + order + " bits", failCount1);
darcy32db4492009-01-26 19:49:26 -0800101 }
102
bpb28090952013-06-19 08:59:39 -0700103 public static void square(int order) {
104 int failCount1 = 0;
105
106 for (int i=0; i<size; i++) {
107 // Test identity x^2 == x*x
108 BigInteger x = fetchNumber(order);
109 BigInteger xx = x.multiply(x);
110 BigInteger x2 = x.pow(2);
111
112 if (!x2.equals(xx))
113 failCount1++;
114 }
115 report("square for " + order + " bits", failCount1);
116 }
117
118 public static void arithmetic(int order) {
darcy32db4492009-01-26 19:49:26 -0800119 int failCount = 0;
120
121 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700122 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800123 while(x.compareTo(BigInteger.ZERO) != 1)
bpb28090952013-06-19 08:59:39 -0700124 x = fetchNumber(order);
125 BigInteger y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800126 while(x.compareTo(y) == -1)
bpb28090952013-06-19 08:59:39 -0700127 y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800128 if (y.equals(BigInteger.ZERO))
129 y = y.add(BigInteger.ONE);
130
bpb28090952013-06-19 08:59:39 -0700131 // Test identity ((x/y))*y + x%y - x == 0
132 // using separate divide() and remainder()
darcy32db4492009-01-26 19:49:26 -0800133 BigInteger baz = x.divide(y);
134 baz = baz.multiply(y);
135 baz = baz.add(x.remainder(y));
136 baz = baz.subtract(x);
137 if (!baz.equals(BigInteger.ZERO))
138 failCount++;
139 }
bpb28090952013-06-19 08:59:39 -0700140 report("Arithmetic I for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800141
142 failCount = 0;
143 for (int i=0; i<100; i++) {
bpb28090952013-06-19 08:59:39 -0700144 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800145 while(x.compareTo(BigInteger.ZERO) != 1)
bpb28090952013-06-19 08:59:39 -0700146 x = fetchNumber(order);
147 BigInteger y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800148 while(x.compareTo(y) == -1)
bpb28090952013-06-19 08:59:39 -0700149 y = fetchNumber(order/2);
darcy32db4492009-01-26 19:49:26 -0800150 if (y.equals(BigInteger.ZERO))
151 y = y.add(BigInteger.ONE);
152
bpb28090952013-06-19 08:59:39 -0700153 // Test identity ((x/y))*y + x%y - x == 0
154 // using divideAndRemainder()
darcy32db4492009-01-26 19:49:26 -0800155 BigInteger baz[] = x.divideAndRemainder(y);
156 baz[0] = baz[0].multiply(y);
157 baz[0] = baz[0].add(baz[1]);
158 baz[0] = baz[0].subtract(x);
159 if (!baz[0].equals(BigInteger.ZERO))
160 failCount++;
161 }
bpb28090952013-06-19 08:59:39 -0700162 report("Arithmetic II for " + order + " bits", failCount);
163 }
164
165 /**
166 * Sanity test for Karatsuba and 3-way Toom-Cook multiplication.
167 * For each of the Karatsuba and 3-way Toom-Cook multiplication thresholds,
168 * construct two factors each with a mag array one element shorter than the
169 * threshold, and with the most significant bit set and the rest of the bits
170 * random. Each of these numbers will therefore be below the threshold but
171 * if shifted left be above the threshold. Call the numbers 'u' and 'v' and
172 * define random shifts 'a' and 'b' in the range [1,32]. Then we have the
173 * identity
174 * <pre>
175 * (u << a)*(v << b) = (u*v) << (a + b)
176 * </pre>
177 * For Karatsuba multiplication, the right hand expression will be evaluated
178 * using the standard naive algorithm, and the left hand expression using
179 * the Karatsuba algorithm. For 3-way Toom-Cook multiplication, the right
180 * hand expression will be evaluated using Karatsuba multiplication, and the
181 * left hand expression using 3-way Toom-Cook multiplication.
182 */
183 public static void multiplyLarge() {
184 int failCount = 0;
185
186 BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA - 32 - 1);
187 for (int i=0; i<size; i++) {
188 BigInteger x = fetchNumber(BITS_KARATSUBA - 32 - 1);
189 BigInteger u = base.add(x);
190 int a = 1 + rnd.nextInt(31);
191 BigInteger w = u.shiftLeft(a);
192
193 BigInteger y = fetchNumber(BITS_KARATSUBA - 32 - 1);
194 BigInteger v = base.add(y);
195 int b = 1 + rnd.nextInt(32);
196 BigInteger z = v.shiftLeft(b);
197
198 BigInteger multiplyResult = u.multiply(v).shiftLeft(a + b);
199 BigInteger karatsubaMultiplyResult = w.multiply(z);
200
201 if (!multiplyResult.equals(karatsubaMultiplyResult)) {
202 failCount++;
203 }
204 }
205
206 report("multiplyLarge Karatsuba", failCount);
207
208 failCount = 0;
209 base = base.shiftLeft(BITS_TOOM_COOK - BITS_KARATSUBA);
210 for (int i=0; i<size; i++) {
211 BigInteger x = fetchNumber(BITS_TOOM_COOK - 32 - 1);
212 BigInteger u = base.add(x);
213 BigInteger u2 = u.shiftLeft(1);
214 BigInteger y = fetchNumber(BITS_TOOM_COOK - 32 - 1);
215 BigInteger v = base.add(y);
216 BigInteger v2 = v.shiftLeft(1);
217
218 BigInteger multiplyResult = u.multiply(v).shiftLeft(2);
219 BigInteger toomCookMultiplyResult = u2.multiply(v2);
220
221 if (!multiplyResult.equals(toomCookMultiplyResult)) {
222 failCount++;
223 }
224 }
225
226 report("multiplyLarge Toom-Cook", failCount);
227 }
228
229 /**
230 * Sanity test for Karatsuba and 3-way Toom-Cook squaring.
231 * This test is analogous to {@link AbstractMethodError#multiplyLarge}
232 * with both factors being equal. The squaring methods will not be tested
233 * unless the <code>bigInteger.multiply(bigInteger)</code> tests whether
234 * the parameter is the same instance on which the method is being invoked
235 * and calls <code>square()</code> accordingly.
236 */
237 public static void squareLarge() {
238 int failCount = 0;
239
240 BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA_SQUARE - 32 - 1);
241 for (int i=0; i<size; i++) {
242 BigInteger x = fetchNumber(BITS_KARATSUBA_SQUARE - 32 - 1);
243 BigInteger u = base.add(x);
244 int a = 1 + rnd.nextInt(31);
245 BigInteger w = u.shiftLeft(a);
246
247 BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
248 BigInteger karatsubaSquareResult = w.multiply(w);
249
250 if (!squareResult.equals(karatsubaSquareResult)) {
251 failCount++;
252 }
253 }
254
255 report("squareLarge Karatsuba", failCount);
256
257 failCount = 0;
258 base = base.shiftLeft(BITS_TOOM_COOK_SQUARE - BITS_KARATSUBA_SQUARE);
259 for (int i=0; i<size; i++) {
260 BigInteger x = fetchNumber(BITS_TOOM_COOK_SQUARE - 32 - 1);
261 BigInteger u = base.add(x);
262 int a = 1 + rnd.nextInt(31);
263 BigInteger w = u.shiftLeft(a);
264
265 BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
266 BigInteger toomCookSquareResult = w.multiply(w);
267
268 if (!squareResult.equals(toomCookSquareResult)) {
269 failCount++;
270 }
271 }
272
273 report("squareLarge Toom-Cook", failCount);
darcy32db4492009-01-26 19:49:26 -0800274 }
275
276 public static void bitCount() {
277 int failCount = 0;
278
279 for (int i=0; i<size*10; i++) {
280 int x = rnd.nextInt();
281 BigInteger bigX = BigInteger.valueOf((long)x);
282 int bit = (x < 0 ? 0 : 1);
283 int tmp = x, bitCount = 0;
284 for (int j=0; j<32; j++) {
285 bitCount += ((tmp & 1) == bit ? 1 : 0);
286 tmp >>= 1;
287 }
288
289 if (bigX.bitCount() != bitCount) {
290 //System.err.println(x+": "+bitCount+", "+bigX.bitCount());
291 failCount++;
292 }
293 }
294 report("Bit Count", failCount);
295 }
296
297 public static void bitLength() {
298 int failCount = 0;
299
300 for (int i=0; i<size*10; i++) {
301 int x = rnd.nextInt();
302 BigInteger bigX = BigInteger.valueOf((long)x);
303 int signBit = (x < 0 ? 0x80000000 : 0);
304 int tmp = x, bitLength, j;
305 for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++)
306 tmp <<= 1;
307 bitLength = 32 - j;
308
309 if (bigX.bitLength() != bitLength) {
310 //System.err.println(x+": "+bitLength+", "+bigX.bitLength());
311 failCount++;
312 }
313 }
314
315 report("BitLength", failCount);
316 }
317
bpb28090952013-06-19 08:59:39 -0700318 public static void bitOps(int order) {
darcy32db4492009-01-26 19:49:26 -0800319 int failCount1 = 0, failCount2 = 0, failCount3 = 0;
320
321 for (int i=0; i<size*5; i++) {
bpb28090952013-06-19 08:59:39 -0700322 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800323 BigInteger y;
324
bpb28090952013-06-19 08:59:39 -0700325 // Test setBit and clearBit (and testBit)
darcy32db4492009-01-26 19:49:26 -0800326 if (x.signum() < 0) {
327 y = BigInteger.valueOf(-1);
328 for (int j=0; j<x.bitLength(); j++)
329 if (!x.testBit(j))
330 y = y.clearBit(j);
331 } else {
332 y = BigInteger.ZERO;
333 for (int j=0; j<x.bitLength(); j++)
334 if (x.testBit(j))
335 y = y.setBit(j);
336 }
337 if (!x.equals(y))
338 failCount1++;
339
bpb28090952013-06-19 08:59:39 -0700340 // Test flipBit (and testBit)
darcy32db4492009-01-26 19:49:26 -0800341 y = BigInteger.valueOf(x.signum()<0 ? -1 : 0);
342 for (int j=0; j<x.bitLength(); j++)
343 if (x.signum()<0 ^ x.testBit(j))
344 y = y.flipBit(j);
345 if (!x.equals(y))
346 failCount2++;
347 }
bpb28090952013-06-19 08:59:39 -0700348 report("clearBit/testBit for " + order + " bits", failCount1);
349 report("flipBit/testBit for " + order + " bits", failCount2);
darcy32db4492009-01-26 19:49:26 -0800350
351 for (int i=0; i<size*5; i++) {
bpb28090952013-06-19 08:59:39 -0700352 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800353
bpb28090952013-06-19 08:59:39 -0700354 // Test getLowestSetBit()
darcy32db4492009-01-26 19:49:26 -0800355 int k = x.getLowestSetBit();
356 if (x.signum() == 0) {
357 if (k != -1)
358 failCount3++;
359 } else {
360 BigInteger z = x.and(x.negate());
361 int j;
362 for (j=0; j<z.bitLength() && !z.testBit(j); j++)
363 ;
364 if (k != j)
365 failCount3++;
366 }
367 }
bpb28090952013-06-19 08:59:39 -0700368 report("getLowestSetBit for " + order + " bits", failCount3);
darcy32db4492009-01-26 19:49:26 -0800369 }
370
bpb28090952013-06-19 08:59:39 -0700371 public static void bitwise(int order) {
darcy32db4492009-01-26 19:49:26 -0800372
bpb28090952013-06-19 08:59:39 -0700373 // Test identity x^y == x|y &~ x&y
darcy32db4492009-01-26 19:49:26 -0800374 int failCount = 0;
375 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700376 BigInteger x = fetchNumber(order);
377 BigInteger y = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800378 BigInteger z = x.xor(y);
379 BigInteger w = x.or(y).andNot(x.and(y));
380 if (!z.equals(w))
381 failCount++;
382 }
bpb28090952013-06-19 08:59:39 -0700383 report("Logic (^ | & ~) for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800384
bpb28090952013-06-19 08:59:39 -0700385 // Test identity x &~ y == ~(~x | y)
darcy32db4492009-01-26 19:49:26 -0800386 failCount = 0;
387 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700388 BigInteger x = fetchNumber(order);
389 BigInteger y = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800390 BigInteger z = x.andNot(y);
391 BigInteger w = x.not().or(y).not();
392 if (!z.equals(w))
393 failCount++;
394 }
bpb28090952013-06-19 08:59:39 -0700395 report("Logic (&~ | ~) for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800396 }
397
bpb28090952013-06-19 08:59:39 -0700398 public static void shift(int order) {
darcy32db4492009-01-26 19:49:26 -0800399 int failCount1 = 0;
400 int failCount2 = 0;
401 int failCount3 = 0;
402
403 for (int i=0; i<100; i++) {
bpb28090952013-06-19 08:59:39 -0700404 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800405 int n = Math.abs(rnd.nextInt()%200);
406
407 if (!x.shiftLeft(n).equals
408 (x.multiply(BigInteger.valueOf(2L).pow(n))))
409 failCount1++;
410
411 BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n));
412 BigInteger z = (x.signum()<0 && y[1].signum()!=0
413 ? y[0].subtract(BigInteger.ONE)
414 : y[0]);
415
416 BigInteger b = x.shiftRight(n);
417
418 if (!b.equals(z)) {
419 System.err.println("Input is "+x.toString(2));
420 System.err.println("shift is "+n);
421
422 System.err.println("Divided "+z.toString(2));
423 System.err.println("Shifted is "+b.toString(2));
424 if (b.toString().equals(z.toString()))
425 System.err.println("Houston, we have a problem.");
426 failCount2++;
427 }
428
429 if (!x.shiftLeft(n).shiftRight(n).equals(x))
430 failCount3++;
431 }
bpb28090952013-06-19 08:59:39 -0700432 report("baz shiftLeft for " + order + " bits", failCount1);
433 report("baz shiftRight for " + order + " bits", failCount2);
434 report("baz shiftLeft/Right for " + order + " bits", failCount3);
darcy32db4492009-01-26 19:49:26 -0800435 }
436
bpb28090952013-06-19 08:59:39 -0700437 public static void divideAndRemainder(int order) {
darcy32db4492009-01-26 19:49:26 -0800438 int failCount1 = 0;
439
440 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700441 BigInteger x = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800442 while(x.compareTo(BigInteger.valueOf(3L)) != 1)
bpb28090952013-06-19 08:59:39 -0700443 x = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800444 BigInteger z = x.divide(BigInteger.valueOf(2L));
445 BigInteger y[] = x.divideAndRemainder(x);
446 if (!y[0].equals(BigInteger.ONE)) {
447 failCount1++;
448 System.err.println("fail1 x :"+x);
449 System.err.println(" y :"+y);
450 }
451 else if (!y[1].equals(BigInteger.ZERO)) {
452 failCount1++;
453 System.err.println("fail2 x :"+x);
454 System.err.println(" y :"+y);
455 }
456
457 y = x.divideAndRemainder(z);
458 if (!y[0].equals(BigInteger.valueOf(2))) {
459 failCount1++;
460 System.err.println("fail3 x :"+x);
461 System.err.println(" y :"+y);
462 }
463 }
bpb28090952013-06-19 08:59:39 -0700464 report("divideAndRemainder for " + order + " bits", failCount1);
darcy32db4492009-01-26 19:49:26 -0800465 }
466
467 public static void stringConv() {
468 int failCount = 0;
469
470 for (int i=0; i<100; i++) {
471 byte xBytes[] = new byte[Math.abs(rnd.nextInt())%100+1];
472 rnd.nextBytes(xBytes);
473 BigInteger x = new BigInteger(xBytes);
474
475 for (int radix=2; radix < 37; radix++) {
476 String result = x.toString(radix);
477 BigInteger test = new BigInteger(result, radix);
478 if (!test.equals(x)) {
479 failCount++;
480 System.err.println("BigInteger toString: "+x);
481 System.err.println("Test: "+test);
482 System.err.println(radix);
483 }
484 }
485 }
486 report("String Conversion", failCount);
487 }
488
bpb28090952013-06-19 08:59:39 -0700489 public static void byteArrayConv(int order) {
darcy32db4492009-01-26 19:49:26 -0800490 int failCount = 0;
491
492 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700493 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800494 while (x.equals(BigInteger.ZERO))
bpb28090952013-06-19 08:59:39 -0700495 x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800496 BigInteger y = new BigInteger(x.toByteArray());
497 if (!x.equals(y)) {
498 failCount++;
499 System.err.println("orig is "+x);
500 System.err.println("new is "+y);
501 }
502 }
bpb28090952013-06-19 08:59:39 -0700503 report("Array Conversion for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800504 }
505
bpb28090952013-06-19 08:59:39 -0700506 public static void modInv(int order) {
darcy32db4492009-01-26 19:49:26 -0800507 int failCount = 0, successCount = 0, nonInvCount = 0;
508
509 for (int i=0; i<size; i++) {
bpb28090952013-06-19 08:59:39 -0700510 BigInteger x = fetchNumber(order);
darcy32db4492009-01-26 19:49:26 -0800511 while(x.equals(BigInteger.ZERO))
bpb28090952013-06-19 08:59:39 -0700512 x = fetchNumber(order);
513 BigInteger m = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800514 while(m.compareTo(BigInteger.ONE) != 1)
bpb28090952013-06-19 08:59:39 -0700515 m = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800516
517 try {
518 BigInteger inv = x.modInverse(m);
519 BigInteger prod = inv.multiply(x).remainder(m);
520
521 if (prod.signum() == -1)
522 prod = prod.add(m);
523
524 if (prod.equals(BigInteger.ONE))
525 successCount++;
526 else
527 failCount++;
528 } catch(ArithmeticException e) {
529 nonInvCount++;
530 }
531 }
bpb28090952013-06-19 08:59:39 -0700532 report("Modular Inverse for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800533 }
534
bpb28090952013-06-19 08:59:39 -0700535 public static void modExp(int order1, int order2) {
darcy32db4492009-01-26 19:49:26 -0800536 int failCount = 0;
537
538 for (int i=0; i<size/10; i++) {
539 BigInteger m = fetchNumber(order1).abs();
540 while(m.compareTo(BigInteger.ONE) != 1)
541 m = fetchNumber(order1).abs();
542 BigInteger base = fetchNumber(order2);
543 BigInteger exp = fetchNumber(8).abs();
544
545 BigInteger z = base.modPow(exp, m);
546 BigInteger w = base.pow(exp.intValue()).mod(m);
547 if (!z.equals(w)) {
548 System.err.println("z is "+z);
549 System.err.println("w is "+w);
550 System.err.println("mod is "+m);
551 System.err.println("base is "+base);
552 System.err.println("exp is "+exp);
553 failCount++;
554 }
555 }
bpb28090952013-06-19 08:59:39 -0700556 report("Exponentiation I for " + order1 + " and " +
557 order2 + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800558 }
559
560 // This test is based on Fermat's theorem
561 // which is not ideal because base must not be multiple of modulus
562 // and modulus must be a prime or pseudoprime (Carmichael number)
bpb28090952013-06-19 08:59:39 -0700563 public static void modExp2(int order) {
darcy32db4492009-01-26 19:49:26 -0800564 int failCount = 0;
565
566 for (int i=0; i<10; i++) {
567 BigInteger m = new BigInteger(100, 5, rnd);
568 while(m.compareTo(BigInteger.ONE) != 1)
569 m = new BigInteger(100, 5, rnd);
570 BigInteger exp = m.subtract(BigInteger.ONE);
bpb28090952013-06-19 08:59:39 -0700571 BigInteger base = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800572 while(base.compareTo(m) != -1)
bpb28090952013-06-19 08:59:39 -0700573 base = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800574 while(base.equals(BigInteger.ZERO))
bpb28090952013-06-19 08:59:39 -0700575 base = fetchNumber(order).abs();
darcy32db4492009-01-26 19:49:26 -0800576
577 BigInteger one = base.modPow(exp, m);
578 if (!one.equals(BigInteger.ONE)) {
579 System.err.println("m is "+m);
580 System.err.println("base is "+base);
581 System.err.println("exp is "+exp);
582 failCount++;
583 }
584 }
bpb28090952013-06-19 08:59:39 -0700585 report("Exponentiation II for " + order + " bits", failCount);
darcy32db4492009-01-26 19:49:26 -0800586 }
587
588 private static final int[] mersenne_powers = {
589 521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937,
590 21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433,
591 1257787, 1398269, 2976221, 3021377, 6972593, 13466917 };
592
593 private static final long[] carmichaels = {
594 561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,
595 62745,63973,75361,101101,115921,126217,162401,172081,188461,252601,
596 278545,294409,314821,334153,340561,399001,410041,449065,488881,512461,
597 225593397919L };
598
599 // Note: testing the larger ones takes too long.
600 private static final int NUM_MERSENNES_TO_TEST = 7;
601 // Note: this constant used for computed Carmichaels, not the array above
602 private static final int NUM_CARMICHAELS_TO_TEST = 5;
603
604 private static final String[] customer_primes = {
605 "120000000000000000000000000000000019",
606 "633825300114114700748351603131",
607 "1461501637330902918203684832716283019651637554291",
608 "779626057591079617852292862756047675913380626199",
609 "857591696176672809403750477631580323575362410491",
610 "910409242326391377348778281801166102059139832131",
611 "929857869954035706722619989283358182285540127919",
612 "961301750640481375785983980066592002055764391999",
613 "1267617700951005189537696547196156120148404630231",
614 "1326015641149969955786344600146607663033642528339" };
615
616 private static final BigInteger ZERO = BigInteger.ZERO;
617 private static final BigInteger ONE = BigInteger.ONE;
618 private static final BigInteger TWO = new BigInteger("2");
619 private static final BigInteger SIX = new BigInteger("6");
620 private static final BigInteger TWELVE = new BigInteger("12");
621 private static final BigInteger EIGHTEEN = new BigInteger("18");
622
623 public static void prime() {
624 BigInteger p1, p2, c1;
625 int failCount = 0;
626
627 // Test consistency
628 for(int i=0; i<10; i++) {
629 p1 = BigInteger.probablePrime(100, rnd);
630 if (!p1.isProbablePrime(100)) {
631 System.err.println("Consistency "+p1.toString(16));
632 failCount++;
633 }
634 }
635
636 // Test some known Mersenne primes (2^n)-1
637 // The array holds the exponents, not the numbers being tested
638 for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) {
639 p1 = new BigInteger("2");
640 p1 = p1.pow(mersenne_powers[i]);
641 p1 = p1.subtract(BigInteger.ONE);
642 if (!p1.isProbablePrime(100)) {
643 System.err.println("Mersenne prime "+i+ " failed.");
644 failCount++;
645 }
646 }
647
648 // Test some primes reported by customers as failing in the past
649 for (int i=0; i<customer_primes.length; i++) {
650 p1 = new BigInteger(customer_primes[i]);
651 if (!p1.isProbablePrime(100)) {
652 System.err.println("Customer prime "+i+ " failed.");
653 failCount++;
654 }
655 }
656
657 // Test some known Carmichael numbers.
658 for (int i=0; i<carmichaels.length; i++) {
659 c1 = BigInteger.valueOf(carmichaels[i]);
660 if(c1.isProbablePrime(100)) {
661 System.err.println("Carmichael "+i+ " reported as prime.");
662 failCount++;
663 }
664 }
665
666 // Test some computed Carmichael numbers.
667 // Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if
668 // each of the factors is prime
669 int found = 0;
670 BigInteger f1 = new BigInteger(40, 100, rnd);
671 while (found < NUM_CARMICHAELS_TO_TEST) {
672 BigInteger k = null;
673 BigInteger f2, f3;
674 f1 = f1.nextProbablePrime();
675 BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX);
676 if (result[1].equals(ZERO)) {
677 k = result[0];
678 f2 = k.multiply(TWELVE).add(ONE);
679 if (f2.isProbablePrime(100)) {
680 f3 = k.multiply(EIGHTEEN).add(ONE);
681 if (f3.isProbablePrime(100)) {
682 c1 = f1.multiply(f2).multiply(f3);
683 if (c1.isProbablePrime(100)) {
684 System.err.println("Computed Carmichael "
685 +c1.toString(16));
686 failCount++;
687 }
688 found++;
689 }
690 }
691 }
692 f1 = f1.add(TWO);
693 }
694
695 // Test some composites that are products of 2 primes
696 for (int i=0; i<50; i++) {
697 p1 = BigInteger.probablePrime(100, rnd);
698 p2 = BigInteger.probablePrime(100, rnd);
699 c1 = p1.multiply(p2);
700 if (c1.isProbablePrime(100)) {
701 System.err.println("Composite failed "+c1.toString(16));
702 failCount++;
703 }
704 }
705
706 for (int i=0; i<4; i++) {
707 p1 = BigInteger.probablePrime(600, rnd);
708 p2 = BigInteger.probablePrime(600, rnd);
709 c1 = p1.multiply(p2);
710 if (c1.isProbablePrime(100)) {
711 System.err.println("Composite failed "+c1.toString(16));
712 failCount++;
713 }
714 }
715
716 report("Prime", failCount);
717 }
718
719 private static final long[] primesTo100 = {
720 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
721 };
722
723 private static final long[] aPrimeSequence = {
724 1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L,
725 1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L,
726 1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L,
727 1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L,
728 1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L,
729 1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L,
730 1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L,
731 1999999853L, 1999999861L, 1999999871L, 1999999873
732 };
733
734 public static void nextProbablePrime() throws Exception {
735 int failCount = 0;
736 BigInteger p1, p2, p3;
737 p1 = p2 = p3 = ZERO;
738
739 // First test nextProbablePrime on the low range starting at zero
740 for (int i=0; i<primesTo100.length; i++) {
741 p1 = p1.nextProbablePrime();
742 if (p1.longValue() != primesTo100[i]) {
743 System.err.println("low range primes failed");
744 System.err.println("p1 is "+p1);
745 System.err.println("expected "+primesTo100[i]);
746 failCount++;
747 }
748 }
749
750 // Test nextProbablePrime on a relatively small, known prime sequence
751 p1 = BigInteger.valueOf(aPrimeSequence[0]);
752 for (int i=1; i<aPrimeSequence.length; i++) {
753 p1 = p1.nextProbablePrime();
754 if (p1.longValue() != aPrimeSequence[i]) {
755 System.err.println("prime sequence failed");
756 failCount++;
757 }
758 }
759
760 // Next, pick some large primes, use nextProbablePrime to find the
761 // next one, and make sure there are no primes in between
762 for (int i=0; i<100; i+=10) {
763 p1 = BigInteger.probablePrime(50 + i, rnd);
764 p2 = p1.add(ONE);
765 p3 = p1.nextProbablePrime();
766 while(p2.compareTo(p3) < 0) {
767 if (p2.isProbablePrime(100)){
768 System.err.println("nextProbablePrime failed");
769 System.err.println("along range "+p1.toString(16));
770 System.err.println("to "+p3.toString(16));
771 failCount++;
772 break;
773 }
774 p2 = p2.add(ONE);
775 }
776 }
777
778 report("nextProbablePrime", failCount);
779 }
780
781 public static void serialize() throws Exception {
782 int failCount = 0;
783
784 String bitPatterns[] = {
785 "ffffffff00000000ffffffff00000000ffffffff00000000",
786 "ffffffffffffffffffffffff000000000000000000000000",
787 "ffffffff0000000000000000000000000000000000000000",
788 "10000000ffffffffffffffffffffffffffffffffffffffff",
789 "100000000000000000000000000000000000000000000000",
790 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
791 "-ffffffff00000000ffffffff00000000ffffffff00000000",
792 "-ffffffffffffffffffffffff000000000000000000000000",
793 "-ffffffff0000000000000000000000000000000000000000",
794 "-10000000ffffffffffffffffffffffffffffffffffffffff",
795 "-100000000000000000000000000000000000000000000000",
796 "-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
797 };
798
799 for(int i = 0; i < bitPatterns.length; i++) {
800 BigInteger b1 = new BigInteger(bitPatterns[i], 16);
darcye5dbfef2009-12-22 21:48:19 -0800801 BigInteger b2 = null;
darcy32db4492009-01-26 19:49:26 -0800802
803 File f = new File("serialtest");
smarks1dba3592011-02-22 15:34:17 -0800804
805 try (FileOutputStream fos = new FileOutputStream(f)) {
806 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
darcye5dbfef2009-12-22 21:48:19 -0800807 oos.writeObject(b1);
808 oos.flush();
darcye5dbfef2009-12-22 21:48:19 -0800809 }
darcy32db4492009-01-26 19:49:26 -0800810
smarks1dba3592011-02-22 15:34:17 -0800811 try (FileInputStream fis = new FileInputStream(f);
812 ObjectInputStream ois = new ObjectInputStream(fis))
813 {
814 b2 = (BigInteger)ois.readObject();
darcye5dbfef2009-12-22 21:48:19 -0800815 }
816
817 if (!b1.equals(b2) ||
818 !b1.equals(b1.or(b2))) {
819 failCount++;
820 System.err.println("Serialized failed for hex " +
821 b1.toString(16));
822 }
darcy32db4492009-01-26 19:49:26 -0800823 }
824 f.delete();
825 }
826
827 for(int i=0; i<10; i++) {
828 BigInteger b1 = fetchNumber(rnd.nextInt(100));
darcye5dbfef2009-12-22 21:48:19 -0800829 BigInteger b2 = null;
darcy32db4492009-01-26 19:49:26 -0800830 File f = new File("serialtest");
smarks1dba3592011-02-22 15:34:17 -0800831 try (FileOutputStream fos = new FileOutputStream(f)) {
832 try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
darcye5dbfef2009-12-22 21:48:19 -0800833 oos.writeObject(b1);
834 oos.flush();
darcye5dbfef2009-12-22 21:48:19 -0800835 }
836
smarks1dba3592011-02-22 15:34:17 -0800837 try (FileInputStream fis = new FileInputStream(f);
838 ObjectInputStream ois = new ObjectInputStream(fis))
839 {
840 b2 = (BigInteger)ois.readObject();
darcye5dbfef2009-12-22 21:48:19 -0800841 }
darcye5dbfef2009-12-22 21:48:19 -0800842 }
darcy32db4492009-01-26 19:49:26 -0800843
844 if (!b1.equals(b2) ||
845 !b1.equals(b1.or(b2)))
846 failCount++;
847 f.delete();
848 }
849
850 report("Serialize", failCount);
851 }
852
853 /**
854 * Main to interpret arguments and run several tests.
855 *
856 * Up to three arguments may be given to specify the size of BigIntegers
857 * used for call parameters 1, 2, and 3. The size is interpreted as
858 * the maximum number of decimal digits that the parameters will have.
859 *
860 */
861 public static void main(String[] args) throws Exception {
862
bpb28090952013-06-19 08:59:39 -0700863 // Some variables for sizing test numbers in bits
864 int order1 = ORDER_MEDIUM;
865 int order2 = ORDER_SMALL;
866 int order3 = ORDER_KARATSUBA;
867 int order4 = ORDER_TOOM_COOK;
868
darcy32db4492009-01-26 19:49:26 -0800869 if (args.length >0)
870 order1 = (int)((Integer.parseInt(args[0]))* 3.333);
871 if (args.length >1)
872 order2 = (int)((Integer.parseInt(args[1]))* 3.333);
873 if (args.length >2)
874 order3 = (int)((Integer.parseInt(args[2]))* 3.333);
bpb28090952013-06-19 08:59:39 -0700875 if (args.length >3)
876 order4 = (int)((Integer.parseInt(args[3]))* 3.333);
darcy32db4492009-01-26 19:49:26 -0800877
878 prime();
879 nextProbablePrime();
880
bpb28090952013-06-19 08:59:39 -0700881 arithmetic(order1); // small numbers
882 arithmetic(order3); // Karatsuba / Burnikel-Ziegler range
883 arithmetic(order4); // Toom-Cook range
884
885 divideAndRemainder(order1); // small numbers
886 divideAndRemainder(order3); // Karatsuba / Burnikel-Ziegler range
887 divideAndRemainder(order4); // Toom-Cook range
888
889 pow(order1);
890 pow(order3);
891 pow(order4);
892
893 square(ORDER_MEDIUM);
894 square(ORDER_KARATSUBA_SQUARE);
895 square(ORDER_TOOM_COOK_SQUARE);
darcy32db4492009-01-26 19:49:26 -0800896
897 bitCount();
898 bitLength();
bpb28090952013-06-19 08:59:39 -0700899 bitOps(order1);
900 bitwise(order1);
darcy32db4492009-01-26 19:49:26 -0800901
bpb28090952013-06-19 08:59:39 -0700902 shift(order1);
darcy32db4492009-01-26 19:49:26 -0800903
bpb28090952013-06-19 08:59:39 -0700904 byteArrayConv(order1);
darcy32db4492009-01-26 19:49:26 -0800905
bpb28090952013-06-19 08:59:39 -0700906 modInv(order1); // small numbers
907 modInv(order3); // Karatsuba / Burnikel-Ziegler range
908 modInv(order4); // Toom-Cook range
909
910 modExp(order1, order2);
911 modExp2(order1);
darcy32db4492009-01-26 19:49:26 -0800912
913 stringConv();
914 serialize();
915
bpb28090952013-06-19 08:59:39 -0700916 multiplyLarge();
917 squareLarge();
918
darcy32db4492009-01-26 19:49:26 -0800919 if (failure)
920 throw new RuntimeException("Failure in BigIntegerTest.");
921 }
922
923 /*
924 * Get a random or boundary-case number. This is designed to provide
925 * a lot of numbers that will find failure points, such as max sized
926 * numbers, empty BigIntegers, etc.
927 *
928 * If order is less than 2, order is changed to 2.
929 */
930 private static BigInteger fetchNumber(int order) {
931 boolean negative = rnd.nextBoolean();
bpb28090952013-06-19 08:59:39 -0700932 int numType = rnd.nextInt(7);
darcy32db4492009-01-26 19:49:26 -0800933 BigInteger result = null;
934 if (order < 2) order = 2;
935
936 switch (numType) {
937 case 0: // Empty
938 result = BigInteger.ZERO;
939 break;
940
941 case 1: // One
942 result = BigInteger.ONE;
943 break;
944
945 case 2: // All bits set in number
946 int numBytes = (order+7)/8;
947 byte[] fullBits = new byte[numBytes];
948 for(int i=0; i<numBytes; i++)
949 fullBits[i] = (byte)0xff;
950 int excessBits = 8*numBytes - order;
951 fullBits[0] &= (1 << (8-excessBits)) - 1;
952 result = new BigInteger(1, fullBits);
953 break;
954
955 case 3: // One bit in number
956 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
957 break;
958
959 case 4: // Random bit density
960 int iterations = rnd.nextInt(order-1);
961 result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
962 for(int i=0; i<iterations; i++) {
963 BigInteger temp = BigInteger.ONE.shiftLeft(
964 rnd.nextInt(order));
965 result = result.or(temp);
966 }
967 break;
bpb28090952013-06-19 08:59:39 -0700968 case 5: // Runs of consecutive ones and zeros
969 result = ZERO;
970 int remaining = order;
971 int bit = rnd.nextInt(2);
972 while (remaining > 0) {
973 int runLength = Math.min(remaining, rnd.nextInt(order));
974 result = result.shiftLeft(runLength);
975 if (bit > 0)
976 result = result.add(ONE.shiftLeft(runLength).subtract(ONE));
977 remaining -= runLength;
978 bit = 1 - bit;
979 }
980 break;
darcy32db4492009-01-26 19:49:26 -0800981
982 default: // random bits
983 result = new BigInteger(order, rnd);
984 }
985
986 if (negative)
987 result = result.negate();
988
989 return result;
990 }
991
992 static void report(String testName, int failCount) {
993 System.err.println(testName+": " +
994 (failCount==0 ? "Passed":"Failed("+failCount+")"));
995 if (failCount > 0)
996 failure = true;
997 }
998}