Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/math/BigInteger/BigIntegerTest.java
38811 views
1
/*
2
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
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
*
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.
22
*/
23
24
/*
25
* @test
26
* @bug 4181191 4161971 4227146 4194389 4823171 4624738 4812225 4837946
27
* @summary tests methods in BigInteger
28
* @run main/timeout=400 BigIntegerTest
29
* @author madbot
30
* @key randomness
31
*/
32
33
import java.io.File;
34
import java.io.FileInputStream;
35
import java.io.FileOutputStream;
36
import java.io.ObjectInputStream;
37
import java.io.ObjectOutputStream;
38
import java.math.BigInteger;
39
import java.util.Random;
40
41
/**
42
* This is a simple test class created to ensure that the results
43
* generated by BigInteger adhere to certain identities. Passing
44
* this test is a strong assurance that the BigInteger operations
45
* are working correctly.
46
*
47
* Four arguments may be specified which give the number of
48
* decimal digits you desire in the four batches of test numbers.
49
*
50
* The tests are performed on arrays of random numbers which are
51
* generated by a Random class as well as special cases which
52
* throw in boundary numbers such as 0, 1, maximum sized, etc.
53
*
54
*/
55
public class BigIntegerTest {
56
//
57
// Bit large number thresholds based on the int thresholds
58
// defined in BigInteger itself:
59
//
60
// KARATSUBA_THRESHOLD = 80 ints = 2560 bits
61
// TOOM_COOK_THRESHOLD = 240 ints = 7680 bits
62
// KARATSUBA_SQUARE_THRESHOLD = 128 ints = 4096 bits
63
// TOOM_COOK_SQUARE_THRESHOLD = 216 ints = 6912 bits
64
//
65
// SCHOENHAGE_BASE_CONVERSION_THRESHOLD = 20 ints = 640 bits
66
//
67
// BURNIKEL_ZIEGLER_THRESHOLD = 80 ints = 2560 bits
68
//
69
static final int BITS_KARATSUBA = 2560;
70
static final int BITS_TOOM_COOK = 7680;
71
static final int BITS_KARATSUBA_SQUARE = 4096;
72
static final int BITS_TOOM_COOK_SQUARE = 6912;
73
static final int BITS_SCHOENHAGE_BASE = 640;
74
static final int BITS_BURNIKEL_ZIEGLER = 2560;
75
static final int BITS_BURNIKEL_ZIEGLER_OFFSET = 1280;
76
77
static final int ORDER_SMALL = 60;
78
static final int ORDER_MEDIUM = 100;
79
// #bits for testing Karatsuba
80
static final int ORDER_KARATSUBA = 2760;
81
// #bits for testing Toom-Cook and Burnikel-Ziegler
82
static final int ORDER_TOOM_COOK = 8000;
83
// #bits for testing Karatsuba squaring
84
static final int ORDER_KARATSUBA_SQUARE = 4200;
85
// #bits for testing Toom-Cook squaring
86
static final int ORDER_TOOM_COOK_SQUARE = 7000;
87
88
static final int SIZE = 1000; // numbers per batch
89
90
static Random rnd = new Random();
91
static boolean failure = false;
92
93
public static void pow(int order) {
94
int failCount1 = 0;
95
96
for (int i=0; i<SIZE; i++) {
97
// Test identity x^power == x*x*x ... *x
98
int power = rnd.nextInt(6) + 2;
99
BigInteger x = fetchNumber(order);
100
BigInteger y = x.pow(power);
101
BigInteger z = x;
102
103
for (int j=1; j<power; j++)
104
z = z.multiply(x);
105
106
if (!y.equals(z))
107
failCount1++;
108
}
109
report("pow for " + order + " bits", failCount1);
110
}
111
112
public static void square(int order) {
113
int failCount1 = 0;
114
115
for (int i=0; i<SIZE; i++) {
116
// Test identity x^2 == x*x
117
BigInteger x = fetchNumber(order);
118
BigInteger xx = x.multiply(x);
119
BigInteger x2 = x.pow(2);
120
121
if (!x2.equals(xx))
122
failCount1++;
123
}
124
report("square for " + order + " bits", failCount1);
125
}
126
127
public static void arithmetic(int order) {
128
int failCount = 0;
129
130
for (int i=0; i<SIZE; i++) {
131
BigInteger x = fetchNumber(order);
132
while(x.compareTo(BigInteger.ZERO) != 1)
133
x = fetchNumber(order);
134
BigInteger y = fetchNumber(order/2);
135
while(x.compareTo(y) == -1)
136
y = fetchNumber(order/2);
137
if (y.equals(BigInteger.ZERO))
138
y = y.add(BigInteger.ONE);
139
140
// Test identity ((x/y))*y + x%y - x == 0
141
// using separate divide() and remainder()
142
BigInteger baz = x.divide(y);
143
baz = baz.multiply(y);
144
baz = baz.add(x.remainder(y));
145
baz = baz.subtract(x);
146
if (!baz.equals(BigInteger.ZERO))
147
failCount++;
148
}
149
report("Arithmetic I for " + order + " bits", failCount);
150
151
failCount = 0;
152
for (int i=0; i<100; i++) {
153
BigInteger x = fetchNumber(order);
154
while(x.compareTo(BigInteger.ZERO) != 1)
155
x = fetchNumber(order);
156
BigInteger y = fetchNumber(order/2);
157
while(x.compareTo(y) == -1)
158
y = fetchNumber(order/2);
159
if (y.equals(BigInteger.ZERO))
160
y = y.add(BigInteger.ONE);
161
162
// Test identity ((x/y))*y + x%y - x == 0
163
// using divideAndRemainder()
164
BigInteger baz[] = x.divideAndRemainder(y);
165
baz[0] = baz[0].multiply(y);
166
baz[0] = baz[0].add(baz[1]);
167
baz[0] = baz[0].subtract(x);
168
if (!baz[0].equals(BigInteger.ZERO))
169
failCount++;
170
}
171
report("Arithmetic II for " + order + " bits", failCount);
172
}
173
174
/**
175
* Sanity test for Karatsuba and 3-way Toom-Cook multiplication.
176
* For each of the Karatsuba and 3-way Toom-Cook multiplication thresholds,
177
* construct two factors each with a mag array one element shorter than the
178
* threshold, and with the most significant bit set and the rest of the bits
179
* random. Each of these numbers will therefore be below the threshold but
180
* if shifted left be above the threshold. Call the numbers 'u' and 'v' and
181
* define random shifts 'a' and 'b' in the range [1,32]. Then we have the
182
* identity
183
* <pre>
184
* (u << a)*(v << b) = (u*v) << (a + b)
185
* </pre>
186
* For Karatsuba multiplication, the right hand expression will be evaluated
187
* using the standard naive algorithm, and the left hand expression using
188
* the Karatsuba algorithm. For 3-way Toom-Cook multiplication, the right
189
* hand expression will be evaluated using Karatsuba multiplication, and the
190
* left hand expression using 3-way Toom-Cook multiplication.
191
*/
192
public static void multiplyLarge() {
193
int failCount = 0;
194
195
BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA - 32 - 1);
196
for (int i=0; i<SIZE; i++) {
197
BigInteger x = fetchNumber(BITS_KARATSUBA - 32 - 1);
198
BigInteger u = base.add(x);
199
int a = 1 + rnd.nextInt(31);
200
BigInteger w = u.shiftLeft(a);
201
202
BigInteger y = fetchNumber(BITS_KARATSUBA - 32 - 1);
203
BigInteger v = base.add(y);
204
int b = 1 + rnd.nextInt(32);
205
BigInteger z = v.shiftLeft(b);
206
207
BigInteger multiplyResult = u.multiply(v).shiftLeft(a + b);
208
BigInteger karatsubaMultiplyResult = w.multiply(z);
209
210
if (!multiplyResult.equals(karatsubaMultiplyResult)) {
211
failCount++;
212
}
213
}
214
215
report("multiplyLarge Karatsuba", failCount);
216
217
failCount = 0;
218
base = base.shiftLeft(BITS_TOOM_COOK - BITS_KARATSUBA);
219
for (int i=0; i<SIZE; i++) {
220
BigInteger x = fetchNumber(BITS_TOOM_COOK - 32 - 1);
221
BigInteger u = base.add(x);
222
BigInteger u2 = u.shiftLeft(1);
223
BigInteger y = fetchNumber(BITS_TOOM_COOK - 32 - 1);
224
BigInteger v = base.add(y);
225
BigInteger v2 = v.shiftLeft(1);
226
227
BigInteger multiplyResult = u.multiply(v).shiftLeft(2);
228
BigInteger toomCookMultiplyResult = u2.multiply(v2);
229
230
if (!multiplyResult.equals(toomCookMultiplyResult)) {
231
failCount++;
232
}
233
}
234
235
report("multiplyLarge Toom-Cook", failCount);
236
}
237
238
/**
239
* Sanity test for Karatsuba and 3-way Toom-Cook squaring.
240
* This test is analogous to {@link AbstractMethodError#multiplyLarge}
241
* with both factors being equal. The squaring methods will not be tested
242
* unless the <code>bigInteger.multiply(bigInteger)</code> tests whether
243
* the parameter is the same instance on which the method is being invoked
244
* and calls <code>square()</code> accordingly.
245
*/
246
public static void squareLarge() {
247
int failCount = 0;
248
249
BigInteger base = BigInteger.ONE.shiftLeft(BITS_KARATSUBA_SQUARE - 32 - 1);
250
for (int i=0; i<SIZE; i++) {
251
BigInteger x = fetchNumber(BITS_KARATSUBA_SQUARE - 32 - 1);
252
BigInteger u = base.add(x);
253
int a = 1 + rnd.nextInt(31);
254
BigInteger w = u.shiftLeft(a);
255
256
BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
257
BigInteger karatsubaSquareResult = w.multiply(w);
258
259
if (!squareResult.equals(karatsubaSquareResult)) {
260
failCount++;
261
}
262
}
263
264
report("squareLarge Karatsuba", failCount);
265
266
failCount = 0;
267
base = base.shiftLeft(BITS_TOOM_COOK_SQUARE - BITS_KARATSUBA_SQUARE);
268
for (int i=0; i<SIZE; i++) {
269
BigInteger x = fetchNumber(BITS_TOOM_COOK_SQUARE - 32 - 1);
270
BigInteger u = base.add(x);
271
int a = 1 + rnd.nextInt(31);
272
BigInteger w = u.shiftLeft(a);
273
274
BigInteger squareResult = u.multiply(u).shiftLeft(2*a);
275
BigInteger toomCookSquareResult = w.multiply(w);
276
277
if (!squareResult.equals(toomCookSquareResult)) {
278
failCount++;
279
}
280
}
281
282
report("squareLarge Toom-Cook", failCount);
283
}
284
285
/**
286
* Sanity test for Burnikel-Ziegler division. The Burnikel-Ziegler division
287
* algorithm is used when each of the dividend and the divisor has at least
288
* a specified number of ints in its representation. This test is based on
289
* the observation that if {@code w = u*pow(2,a)} and {@code z = v*pow(2,b)}
290
* where {@code abs(u) > abs(v)} and {@code a > b && b > 0}, then if
291
* {@code w/z = q1*z + r1} and {@code u/v = q2*v + r2}, then
292
* {@code q1 = q2*pow(2,a-b)} and {@code r1 = r2*pow(2,b)}. The test
293
* ensures that {@code v} is just under the B-Z threshold, that {@code z} is
294
* over the threshold and {@code w} is much larger than {@code z}. This
295
* implies that {@code u/v} uses the standard division algorithm and
296
* {@code w/z} uses the B-Z algorithm. The results of the two algorithms
297
* are then compared using the observation described in the foregoing and
298
* if they are not equal a failure is logged.
299
*/
300
public static void divideLarge() {
301
int failCount = 0;
302
303
BigInteger base = BigInteger.ONE.shiftLeft(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 33);
304
for (int i=0; i<SIZE; i++) {
305
BigInteger addend = new BigInteger(BITS_BURNIKEL_ZIEGLER + BITS_BURNIKEL_ZIEGLER_OFFSET - 34, rnd);
306
BigInteger v = base.add(addend);
307
308
BigInteger u = v.multiply(BigInteger.valueOf(2 + rnd.nextInt(Short.MAX_VALUE - 1)));
309
310
if(rnd.nextBoolean()) {
311
u = u.negate();
312
}
313
if(rnd.nextBoolean()) {
314
v = v.negate();
315
}
316
317
int a = BITS_BURNIKEL_ZIEGLER_OFFSET + rnd.nextInt(16);
318
int b = 1 + rnd.nextInt(16);
319
BigInteger w = u.multiply(BigInteger.ONE.shiftLeft(a));
320
BigInteger z = v.multiply(BigInteger.ONE.shiftLeft(b));
321
322
BigInteger[] divideResult = u.divideAndRemainder(v);
323
divideResult[0] = divideResult[0].multiply(BigInteger.ONE.shiftLeft(a - b));
324
divideResult[1] = divideResult[1].multiply(BigInteger.ONE.shiftLeft(b));
325
BigInteger[] bzResult = w.divideAndRemainder(z);
326
327
if (divideResult[0].compareTo(bzResult[0]) != 0 ||
328
divideResult[1].compareTo(bzResult[1]) != 0) {
329
failCount++;
330
}
331
}
332
333
report("divideLarge", failCount);
334
}
335
336
public static void bitCount() {
337
int failCount = 0;
338
339
for (int i=0; i<SIZE*10; i++) {
340
int x = rnd.nextInt();
341
BigInteger bigX = BigInteger.valueOf((long)x);
342
int bit = (x < 0 ? 0 : 1);
343
int tmp = x, bitCount = 0;
344
for (int j=0; j<32; j++) {
345
bitCount += ((tmp & 1) == bit ? 1 : 0);
346
tmp >>= 1;
347
}
348
349
if (bigX.bitCount() != bitCount) {
350
//System.err.println(x+": "+bitCount+", "+bigX.bitCount());
351
failCount++;
352
}
353
}
354
report("Bit Count", failCount);
355
}
356
357
public static void bitLength() {
358
int failCount = 0;
359
360
for (int i=0; i<SIZE*10; i++) {
361
int x = rnd.nextInt();
362
BigInteger bigX = BigInteger.valueOf((long)x);
363
int signBit = (x < 0 ? 0x80000000 : 0);
364
int tmp = x, bitLength, j;
365
for (j=0; j<32 && (tmp & 0x80000000)==signBit; j++)
366
tmp <<= 1;
367
bitLength = 32 - j;
368
369
if (bigX.bitLength() != bitLength) {
370
//System.err.println(x+": "+bitLength+", "+bigX.bitLength());
371
failCount++;
372
}
373
}
374
375
report("BitLength", failCount);
376
}
377
378
public static void bitOps(int order) {
379
int failCount1 = 0, failCount2 = 0, failCount3 = 0;
380
381
for (int i=0; i<SIZE*5; i++) {
382
BigInteger x = fetchNumber(order);
383
BigInteger y;
384
385
// Test setBit and clearBit (and testBit)
386
if (x.signum() < 0) {
387
y = BigInteger.valueOf(-1);
388
for (int j=0; j<x.bitLength(); j++)
389
if (!x.testBit(j))
390
y = y.clearBit(j);
391
} else {
392
y = BigInteger.ZERO;
393
for (int j=0; j<x.bitLength(); j++)
394
if (x.testBit(j))
395
y = y.setBit(j);
396
}
397
if (!x.equals(y))
398
failCount1++;
399
400
// Test flipBit (and testBit)
401
y = BigInteger.valueOf(x.signum()<0 ? -1 : 0);
402
for (int j=0; j<x.bitLength(); j++)
403
if (x.signum()<0 ^ x.testBit(j))
404
y = y.flipBit(j);
405
if (!x.equals(y))
406
failCount2++;
407
}
408
report("clearBit/testBit for " + order + " bits", failCount1);
409
report("flipBit/testBit for " + order + " bits", failCount2);
410
411
for (int i=0; i<SIZE*5; i++) {
412
BigInteger x = fetchNumber(order);
413
414
// Test getLowestSetBit()
415
int k = x.getLowestSetBit();
416
if (x.signum() == 0) {
417
if (k != -1)
418
failCount3++;
419
} else {
420
BigInteger z = x.and(x.negate());
421
int j;
422
for (j=0; j<z.bitLength() && !z.testBit(j); j++)
423
;
424
if (k != j)
425
failCount3++;
426
}
427
}
428
report("getLowestSetBit for " + order + " bits", failCount3);
429
}
430
431
public static void bitwise(int order) {
432
433
// Test identity x^y == x|y &~ x&y
434
int failCount = 0;
435
for (int i=0; i<SIZE; i++) {
436
BigInteger x = fetchNumber(order);
437
BigInteger y = fetchNumber(order);
438
BigInteger z = x.xor(y);
439
BigInteger w = x.or(y).andNot(x.and(y));
440
if (!z.equals(w))
441
failCount++;
442
}
443
report("Logic (^ | & ~) for " + order + " bits", failCount);
444
445
// Test identity x &~ y == ~(~x | y)
446
failCount = 0;
447
for (int i=0; i<SIZE; i++) {
448
BigInteger x = fetchNumber(order);
449
BigInteger y = fetchNumber(order);
450
BigInteger z = x.andNot(y);
451
BigInteger w = x.not().or(y).not();
452
if (!z.equals(w))
453
failCount++;
454
}
455
report("Logic (&~ | ~) for " + order + " bits", failCount);
456
}
457
458
public static void shift(int order) {
459
int failCount1 = 0;
460
int failCount2 = 0;
461
int failCount3 = 0;
462
463
for (int i=0; i<100; i++) {
464
BigInteger x = fetchNumber(order);
465
int n = Math.abs(rnd.nextInt()%200);
466
467
if (!x.shiftLeft(n).equals
468
(x.multiply(BigInteger.valueOf(2L).pow(n))))
469
failCount1++;
470
471
BigInteger y[] =x.divideAndRemainder(BigInteger.valueOf(2L).pow(n));
472
BigInteger z = (x.signum()<0 && y[1].signum()!=0
473
? y[0].subtract(BigInteger.ONE)
474
: y[0]);
475
476
BigInteger b = x.shiftRight(n);
477
478
if (!b.equals(z)) {
479
System.err.println("Input is "+x.toString(2));
480
System.err.println("shift is "+n);
481
482
System.err.println("Divided "+z.toString(2));
483
System.err.println("Shifted is "+b.toString(2));
484
if (b.toString().equals(z.toString()))
485
System.err.println("Houston, we have a problem.");
486
failCount2++;
487
}
488
489
if (!x.shiftLeft(n).shiftRight(n).equals(x))
490
failCount3++;
491
}
492
report("baz shiftLeft for " + order + " bits", failCount1);
493
report("baz shiftRight for " + order + " bits", failCount2);
494
report("baz shiftLeft/Right for " + order + " bits", failCount3);
495
}
496
497
public static void divideAndRemainder(int order) {
498
int failCount1 = 0;
499
500
for (int i=0; i<SIZE; i++) {
501
BigInteger x = fetchNumber(order).abs();
502
while(x.compareTo(BigInteger.valueOf(3L)) != 1)
503
x = fetchNumber(order).abs();
504
BigInteger z = x.divide(BigInteger.valueOf(2L));
505
BigInteger y[] = x.divideAndRemainder(x);
506
if (!y[0].equals(BigInteger.ONE)) {
507
failCount1++;
508
System.err.println("fail1 x :"+x);
509
System.err.println(" y :"+y);
510
}
511
else if (!y[1].equals(BigInteger.ZERO)) {
512
failCount1++;
513
System.err.println("fail2 x :"+x);
514
System.err.println(" y :"+y);
515
}
516
517
y = x.divideAndRemainder(z);
518
if (!y[0].equals(BigInteger.valueOf(2))) {
519
failCount1++;
520
System.err.println("fail3 x :"+x);
521
System.err.println(" y :"+y);
522
}
523
}
524
report("divideAndRemainder for " + order + " bits", failCount1);
525
}
526
527
public static void stringConv() {
528
int failCount = 0;
529
530
// Generic string conversion.
531
for (int i=0; i<100; i++) {
532
byte xBytes[] = new byte[Math.abs(rnd.nextInt())%100+1];
533
rnd.nextBytes(xBytes);
534
BigInteger x = new BigInteger(xBytes);
535
536
for (int radix=Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) {
537
String result = x.toString(radix);
538
BigInteger test = new BigInteger(result, radix);
539
if (!test.equals(x)) {
540
failCount++;
541
System.err.println("BigInteger toString: "+x);
542
System.err.println("Test: "+test);
543
System.err.println(radix);
544
}
545
}
546
}
547
548
// String conversion straddling the Schoenhage algorithm crossover
549
// threshold, and at twice and four times the threshold.
550
for (int k = 0; k <= 2; k++) {
551
int factor = 1 << k;
552
int upper = factor * BITS_SCHOENHAGE_BASE + 33;
553
int lower = upper - 35;
554
555
for (int bits = upper; bits >= lower; bits--) {
556
for (int i = 0; i < 50; i++) {
557
BigInteger x = BigInteger.ONE.shiftLeft(bits - 1).or(new BigInteger(bits - 2, rnd));
558
559
for (int radix = Character.MIN_RADIX; radix < Character.MAX_RADIX; radix++) {
560
String result = x.toString(radix);
561
BigInteger test = new BigInteger(result, radix);
562
if (!test.equals(x)) {
563
failCount++;
564
System.err.println("BigInteger toString: " + x);
565
System.err.println("Test: " + test);
566
System.err.println(radix);
567
}
568
}
569
}
570
}
571
}
572
573
report("String Conversion", failCount);
574
}
575
576
public static void byteArrayConv(int order) {
577
int failCount = 0;
578
579
for (int i=0; i<SIZE; i++) {
580
BigInteger x = fetchNumber(order);
581
while (x.equals(BigInteger.ZERO))
582
x = fetchNumber(order);
583
BigInteger y = new BigInteger(x.toByteArray());
584
if (!x.equals(y)) {
585
failCount++;
586
System.err.println("orig is "+x);
587
System.err.println("new is "+y);
588
}
589
}
590
report("Array Conversion for " + order + " bits", failCount);
591
}
592
593
public static void modInv(int order) {
594
int failCount = 0, successCount = 0, nonInvCount = 0;
595
596
for (int i=0; i<SIZE; i++) {
597
BigInteger x = fetchNumber(order);
598
while(x.equals(BigInteger.ZERO))
599
x = fetchNumber(order);
600
BigInteger m = fetchNumber(order).abs();
601
while(m.compareTo(BigInteger.ONE) != 1)
602
m = fetchNumber(order).abs();
603
604
try {
605
BigInteger inv = x.modInverse(m);
606
BigInteger prod = inv.multiply(x).remainder(m);
607
608
if (prod.signum() == -1)
609
prod = prod.add(m);
610
611
if (prod.equals(BigInteger.ONE))
612
successCount++;
613
else
614
failCount++;
615
} catch(ArithmeticException e) {
616
nonInvCount++;
617
}
618
}
619
report("Modular Inverse for " + order + " bits", failCount);
620
}
621
622
public static void modExp(int order1, int order2) {
623
int failCount = 0;
624
625
for (int i=0; i<SIZE/10; i++) {
626
BigInteger m = fetchNumber(order1).abs();
627
while(m.compareTo(BigInteger.ONE) != 1)
628
m = fetchNumber(order1).abs();
629
BigInteger base = fetchNumber(order2);
630
BigInteger exp = fetchNumber(8).abs();
631
632
BigInteger z = base.modPow(exp, m);
633
BigInteger w = base.pow(exp.intValue()).mod(m);
634
if (!z.equals(w)) {
635
System.err.println("z is "+z);
636
System.err.println("w is "+w);
637
System.err.println("mod is "+m);
638
System.err.println("base is "+base);
639
System.err.println("exp is "+exp);
640
failCount++;
641
}
642
}
643
report("Exponentiation I for " + order1 + " and " +
644
order2 + " bits", failCount);
645
}
646
647
// This test is based on Fermat's theorem
648
// which is not ideal because base must not be multiple of modulus
649
// and modulus must be a prime or pseudoprime (Carmichael number)
650
public static void modExp2(int order) {
651
int failCount = 0;
652
653
for (int i=0; i<10; i++) {
654
BigInteger m = new BigInteger(100, 5, rnd);
655
while(m.compareTo(BigInteger.ONE) != 1)
656
m = new BigInteger(100, 5, rnd);
657
BigInteger exp = m.subtract(BigInteger.ONE);
658
BigInteger base = fetchNumber(order).abs();
659
while(base.compareTo(m) != -1)
660
base = fetchNumber(order).abs();
661
while(base.equals(BigInteger.ZERO))
662
base = fetchNumber(order).abs();
663
664
BigInteger one = base.modPow(exp, m);
665
if (!one.equals(BigInteger.ONE)) {
666
System.err.println("m is "+m);
667
System.err.println("base is "+base);
668
System.err.println("exp is "+exp);
669
failCount++;
670
}
671
}
672
report("Exponentiation II for " + order + " bits", failCount);
673
}
674
675
private static final int[] mersenne_powers = {
676
521, 607, 1279, 2203, 2281, 3217, 4253, 4423, 9689, 9941, 11213, 19937,
677
21701, 23209, 44497, 86243, 110503, 132049, 216091, 756839, 859433,
678
1257787, 1398269, 2976221, 3021377, 6972593, 13466917 };
679
680
private static final long[] carmichaels = {
681
561,1105,1729,2465,2821,6601,8911,10585,15841,29341,41041,46657,52633,
682
62745,63973,75361,101101,115921,126217,162401,172081,188461,252601,
683
278545,294409,314821,334153,340561,399001,410041,449065,488881,512461,
684
225593397919L };
685
686
// Note: testing the larger ones takes too long.
687
private static final int NUM_MERSENNES_TO_TEST = 7;
688
// Note: this constant used for computed Carmichaels, not the array above
689
private static final int NUM_CARMICHAELS_TO_TEST = 5;
690
691
private static final String[] customer_primes = {
692
"120000000000000000000000000000000019",
693
"633825300114114700748351603131",
694
"1461501637330902918203684832716283019651637554291",
695
"779626057591079617852292862756047675913380626199",
696
"857591696176672809403750477631580323575362410491",
697
"910409242326391377348778281801166102059139832131",
698
"929857869954035706722619989283358182285540127919",
699
"961301750640481375785983980066592002055764391999",
700
"1267617700951005189537696547196156120148404630231",
701
"1326015641149969955786344600146607663033642528339" };
702
703
private static final BigInteger ZERO = BigInteger.ZERO;
704
private static final BigInteger ONE = BigInteger.ONE;
705
private static final BigInteger TWO = new BigInteger("2");
706
private static final BigInteger SIX = new BigInteger("6");
707
private static final BigInteger TWELVE = new BigInteger("12");
708
private static final BigInteger EIGHTEEN = new BigInteger("18");
709
710
public static void prime() {
711
BigInteger p1, p2, c1;
712
int failCount = 0;
713
714
// Test consistency
715
for(int i=0; i<10; i++) {
716
p1 = BigInteger.probablePrime(100, rnd);
717
if (!p1.isProbablePrime(100)) {
718
System.err.println("Consistency "+p1.toString(16));
719
failCount++;
720
}
721
}
722
723
// Test some known Mersenne primes (2^n)-1
724
// The array holds the exponents, not the numbers being tested
725
for (int i=0; i<NUM_MERSENNES_TO_TEST; i++) {
726
p1 = new BigInteger("2");
727
p1 = p1.pow(mersenne_powers[i]);
728
p1 = p1.subtract(BigInteger.ONE);
729
if (!p1.isProbablePrime(100)) {
730
System.err.println("Mersenne prime "+i+ " failed.");
731
failCount++;
732
}
733
}
734
735
// Test some primes reported by customers as failing in the past
736
for (int i=0; i<customer_primes.length; i++) {
737
p1 = new BigInteger(customer_primes[i]);
738
if (!p1.isProbablePrime(100)) {
739
System.err.println("Customer prime "+i+ " failed.");
740
failCount++;
741
}
742
}
743
744
// Test some known Carmichael numbers.
745
for (int i=0; i<carmichaels.length; i++) {
746
c1 = BigInteger.valueOf(carmichaels[i]);
747
if(c1.isProbablePrime(100)) {
748
System.err.println("Carmichael "+i+ " reported as prime.");
749
failCount++;
750
}
751
}
752
753
// Test some computed Carmichael numbers.
754
// Numbers of the form (6k+1)(12k+1)(18k+1) are Carmichael numbers if
755
// each of the factors is prime
756
int found = 0;
757
BigInteger f1 = new BigInteger(40, 100, rnd);
758
while (found < NUM_CARMICHAELS_TO_TEST) {
759
BigInteger k = null;
760
BigInteger f2, f3;
761
f1 = f1.nextProbablePrime();
762
BigInteger[] result = f1.subtract(ONE).divideAndRemainder(SIX);
763
if (result[1].equals(ZERO)) {
764
k = result[0];
765
f2 = k.multiply(TWELVE).add(ONE);
766
if (f2.isProbablePrime(100)) {
767
f3 = k.multiply(EIGHTEEN).add(ONE);
768
if (f3.isProbablePrime(100)) {
769
c1 = f1.multiply(f2).multiply(f3);
770
if (c1.isProbablePrime(100)) {
771
System.err.println("Computed Carmichael "
772
+c1.toString(16));
773
failCount++;
774
}
775
found++;
776
}
777
}
778
}
779
f1 = f1.add(TWO);
780
}
781
782
// Test some composites that are products of 2 primes
783
for (int i=0; i<50; i++) {
784
p1 = BigInteger.probablePrime(100, rnd);
785
p2 = BigInteger.probablePrime(100, rnd);
786
c1 = p1.multiply(p2);
787
if (c1.isProbablePrime(100)) {
788
System.err.println("Composite failed "+c1.toString(16));
789
failCount++;
790
}
791
}
792
793
for (int i=0; i<4; i++) {
794
p1 = BigInteger.probablePrime(600, rnd);
795
p2 = BigInteger.probablePrime(600, rnd);
796
c1 = p1.multiply(p2);
797
if (c1.isProbablePrime(100)) {
798
System.err.println("Composite failed "+c1.toString(16));
799
failCount++;
800
}
801
}
802
803
report("Prime", failCount);
804
}
805
806
private static final long[] primesTo100 = {
807
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
808
};
809
810
private static final long[] aPrimeSequence = {
811
1999999003L, 1999999013L, 1999999049L, 1999999061L, 1999999081L,
812
1999999087L, 1999999093L, 1999999097L, 1999999117L, 1999999121L,
813
1999999151L, 1999999171L, 1999999207L, 1999999219L, 1999999271L,
814
1999999321L, 1999999373L, 1999999423L, 1999999439L, 1999999499L,
815
1999999553L, 1999999559L, 1999999571L, 1999999609L, 1999999613L,
816
1999999621L, 1999999643L, 1999999649L, 1999999657L, 1999999747L,
817
1999999763L, 1999999777L, 1999999811L, 1999999817L, 1999999829L,
818
1999999853L, 1999999861L, 1999999871L, 1999999873
819
};
820
821
public static void nextProbablePrime() throws Exception {
822
int failCount = 0;
823
BigInteger p1, p2, p3;
824
p1 = p2 = p3 = ZERO;
825
826
// First test nextProbablePrime on the low range starting at zero
827
for (int i=0; i<primesTo100.length; i++) {
828
p1 = p1.nextProbablePrime();
829
if (p1.longValue() != primesTo100[i]) {
830
System.err.println("low range primes failed");
831
System.err.println("p1 is "+p1);
832
System.err.println("expected "+primesTo100[i]);
833
failCount++;
834
}
835
}
836
837
// Test nextProbablePrime on a relatively small, known prime sequence
838
p1 = BigInteger.valueOf(aPrimeSequence[0]);
839
for (int i=1; i<aPrimeSequence.length; i++) {
840
p1 = p1.nextProbablePrime();
841
if (p1.longValue() != aPrimeSequence[i]) {
842
System.err.println("prime sequence failed");
843
failCount++;
844
}
845
}
846
847
// Next, pick some large primes, use nextProbablePrime to find the
848
// next one, and make sure there are no primes in between
849
for (int i=0; i<100; i+=10) {
850
p1 = BigInteger.probablePrime(50 + i, rnd);
851
p2 = p1.add(ONE);
852
p3 = p1.nextProbablePrime();
853
while(p2.compareTo(p3) < 0) {
854
if (p2.isProbablePrime(100)){
855
System.err.println("nextProbablePrime failed");
856
System.err.println("along range "+p1.toString(16));
857
System.err.println("to "+p3.toString(16));
858
failCount++;
859
break;
860
}
861
p2 = p2.add(ONE);
862
}
863
}
864
865
report("nextProbablePrime", failCount);
866
}
867
868
public static void serialize() throws Exception {
869
int failCount = 0;
870
871
String bitPatterns[] = {
872
"ffffffff00000000ffffffff00000000ffffffff00000000",
873
"ffffffffffffffffffffffff000000000000000000000000",
874
"ffffffff0000000000000000000000000000000000000000",
875
"10000000ffffffffffffffffffffffffffffffffffffffff",
876
"100000000000000000000000000000000000000000000000",
877
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
878
"-ffffffff00000000ffffffff00000000ffffffff00000000",
879
"-ffffffffffffffffffffffff000000000000000000000000",
880
"-ffffffff0000000000000000000000000000000000000000",
881
"-10000000ffffffffffffffffffffffffffffffffffffffff",
882
"-100000000000000000000000000000000000000000000000",
883
"-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
884
};
885
886
for(int i = 0; i < bitPatterns.length; i++) {
887
BigInteger b1 = new BigInteger(bitPatterns[i], 16);
888
BigInteger b2 = null;
889
890
File f = new File("serialtest");
891
892
try (FileOutputStream fos = new FileOutputStream(f)) {
893
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
894
oos.writeObject(b1);
895
oos.flush();
896
}
897
898
try (FileInputStream fis = new FileInputStream(f);
899
ObjectInputStream ois = new ObjectInputStream(fis))
900
{
901
b2 = (BigInteger)ois.readObject();
902
}
903
904
if (!b1.equals(b2) ||
905
!b1.equals(b1.or(b2))) {
906
failCount++;
907
System.err.println("Serialized failed for hex " +
908
b1.toString(16));
909
}
910
}
911
f.delete();
912
}
913
914
for(int i=0; i<10; i++) {
915
BigInteger b1 = fetchNumber(rnd.nextInt(100));
916
BigInteger b2 = null;
917
File f = new File("serialtest");
918
try (FileOutputStream fos = new FileOutputStream(f)) {
919
try (ObjectOutputStream oos = new ObjectOutputStream(fos)) {
920
oos.writeObject(b1);
921
oos.flush();
922
}
923
924
try (FileInputStream fis = new FileInputStream(f);
925
ObjectInputStream ois = new ObjectInputStream(fis))
926
{
927
b2 = (BigInteger)ois.readObject();
928
}
929
}
930
931
if (!b1.equals(b2) ||
932
!b1.equals(b1.or(b2)))
933
failCount++;
934
f.delete();
935
}
936
937
report("Serialize", failCount);
938
}
939
940
/**
941
* Main to interpret arguments and run several tests.
942
*
943
* Up to three arguments may be given to specify the SIZE of BigIntegers
944
* used for call parameters 1, 2, and 3. The SIZE is interpreted as
945
* the maximum number of decimal digits that the parameters will have.
946
*
947
*/
948
public static void main(String[] args) throws Exception {
949
950
// Some variables for sizing test numbers in bits
951
int order1 = ORDER_MEDIUM;
952
int order2 = ORDER_SMALL;
953
int order3 = ORDER_KARATSUBA;
954
int order4 = ORDER_TOOM_COOK;
955
956
if (args.length >0)
957
order1 = (int)((Integer.parseInt(args[0]))* 3.333);
958
if (args.length >1)
959
order2 = (int)((Integer.parseInt(args[1]))* 3.333);
960
if (args.length >2)
961
order3 = (int)((Integer.parseInt(args[2]))* 3.333);
962
if (args.length >3)
963
order4 = (int)((Integer.parseInt(args[3]))* 3.333);
964
965
prime();
966
nextProbablePrime();
967
968
arithmetic(order1); // small numbers
969
arithmetic(order3); // Karatsuba range
970
arithmetic(order4); // Toom-Cook / Burnikel-Ziegler range
971
972
divideAndRemainder(order1); // small numbers
973
divideAndRemainder(order3); // Karatsuba range
974
divideAndRemainder(order4); // Toom-Cook / Burnikel-Ziegler range
975
976
pow(order1);
977
pow(order3);
978
pow(order4);
979
980
square(ORDER_MEDIUM);
981
square(ORDER_KARATSUBA_SQUARE);
982
square(ORDER_TOOM_COOK_SQUARE);
983
984
bitCount();
985
bitLength();
986
bitOps(order1);
987
bitwise(order1);
988
989
shift(order1);
990
991
byteArrayConv(order1);
992
993
modInv(order1); // small numbers
994
modInv(order3); // Karatsuba range
995
modInv(order4); // Toom-Cook / Burnikel-Ziegler range
996
997
modExp(order1, order2);
998
modExp2(order1);
999
1000
stringConv();
1001
serialize();
1002
1003
multiplyLarge();
1004
squareLarge();
1005
divideLarge();
1006
1007
if (failure)
1008
throw new RuntimeException("Failure in BigIntegerTest.");
1009
}
1010
1011
/*
1012
* Get a random or boundary-case number. This is designed to provide
1013
* a lot of numbers that will find failure points, such as max sized
1014
* numbers, empty BigIntegers, etc.
1015
*
1016
* If order is less than 2, order is changed to 2.
1017
*/
1018
private static BigInteger fetchNumber(int order) {
1019
boolean negative = rnd.nextBoolean();
1020
int numType = rnd.nextInt(7);
1021
BigInteger result = null;
1022
if (order < 2) order = 2;
1023
1024
switch (numType) {
1025
case 0: // Empty
1026
result = BigInteger.ZERO;
1027
break;
1028
1029
case 1: // One
1030
result = BigInteger.ONE;
1031
break;
1032
1033
case 2: // All bits set in number
1034
int numBytes = (order+7)/8;
1035
byte[] fullBits = new byte[numBytes];
1036
for(int i=0; i<numBytes; i++)
1037
fullBits[i] = (byte)0xff;
1038
int excessBits = 8*numBytes - order;
1039
fullBits[0] &= (1 << (8-excessBits)) - 1;
1040
result = new BigInteger(1, fullBits);
1041
break;
1042
1043
case 3: // One bit in number
1044
result = BigInteger.ONE.shiftLeft(rnd.nextInt(order));
1045
break;
1046
1047
case 4: // Random bit density
1048
byte[] val = new byte[(order+7)/8];
1049
int iterations = rnd.nextInt(order);
1050
for (int i=0; i<iterations; i++) {
1051
int bitIdx = rnd.nextInt(order);
1052
val[bitIdx/8] |= 1 << (bitIdx%8);
1053
}
1054
result = new BigInteger(1, val);
1055
break;
1056
case 5: // Runs of consecutive ones and zeros
1057
result = ZERO;
1058
int remaining = order;
1059
int bit = rnd.nextInt(2);
1060
while (remaining > 0) {
1061
int runLength = Math.min(remaining, rnd.nextInt(order));
1062
result = result.shiftLeft(runLength);
1063
if (bit > 0)
1064
result = result.add(ONE.shiftLeft(runLength).subtract(ONE));
1065
remaining -= runLength;
1066
bit = 1 - bit;
1067
}
1068
break;
1069
1070
default: // random bits
1071
result = new BigInteger(order, rnd);
1072
}
1073
1074
if (negative)
1075
result = result.negate();
1076
1077
return result;
1078
}
1079
1080
static void report(String testName, int failCount) {
1081
System.err.println(testName+": " +
1082
(failCount==0 ? "Passed":"Failed("+failCount+")"));
1083
if (failCount > 0)
1084
failure = true;
1085
}
1086
}
1087
1088