• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 package test.jdk.internal.math.FloatingDecimal;
25 
26 import java.math.BigInteger;
27 import java.util.Random;
28 import jdk.internal.math.FDBigInteger;
29 
30 /**
31  * @test
32  * @bug 7032154
33  * @summary unit testys of FDBigInteger
34  * @modules java.base/jdk.internal.math
35  * @author Dmitry Nadezhin
36  */
37 public class TestFDBigInteger {
38 
39     private static final int MAX_P5 = 413;
40     private static final int MAX_P2 = 65;
41     private static final long LONG_SIGN_MASK = (1L << 63);
42     private static final BigInteger FIVE = BigInteger.valueOf(5);
43     private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
44     private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
45     private static final FDBigInteger IMMUTABLE_MILLION = genMillion1();
46     private static final FDBigInteger IMMUTABLE_BILLION = genBillion1();
47     private static final FDBigInteger IMMUTABLE_TEN18 = genTen18();
48 
49     static {
IMMUTABLE_ZERO.makeImmutable()50         IMMUTABLE_ZERO.makeImmutable();
IMMUTABLE_MILLION.makeImmutable()51         IMMUTABLE_MILLION.makeImmutable();
IMMUTABLE_BILLION.makeImmutable()52         IMMUTABLE_BILLION.makeImmutable();
IMMUTABLE_TEN18.makeImmutable()53         IMMUTABLE_TEN18.makeImmutable();
54     }
55 
mutable(String hex, int offset)56     private static FDBigInteger mutable(String hex, int offset) {
57         char[] chars = new BigInteger(hex, 16).toString().toCharArray();
58         return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32);
59     }
60 
immutable(String hex, int offset)61     private static FDBigInteger immutable(String hex, int offset) {
62         FDBigInteger fd = mutable(hex, offset);
63         fd.makeImmutable();
64         return fd;
65     }
66 
biPow52(int p5, int p2)67     private static BigInteger biPow52(int p5, int p2) {
68         return FIVE.pow(p5).shiftLeft(p2);
69     }
70 
71     // data.length == 1, nWords == 1, offset == 0
genMillion1()72     private static FDBigInteger genMillion1() {
73         return FDBigInteger.valueOfPow52(6, 0).leftShift(6);
74     }
75 
76     // data.length == 2, nWords == 1, offset == 0
genMillion2()77     private static FDBigInteger genMillion2() {
78         return FDBigInteger.valueOfMulPow52(1000000L, 0, 0);
79     }
80 
81     // data.length == 1, nWords == 1, offset == 0
genBillion1()82     private static FDBigInteger genBillion1() {
83         return FDBigInteger.valueOfPow52(9, 0).leftShift(9);
84     }
85 
86     // data.length == 2, nWords == 2, offset == 0
genTen18()87     private static FDBigInteger genTen18() {
88         return FDBigInteger.valueOfPow52(18, 0).leftShift(18);
89     }
90 
check(BigInteger expected, FDBigInteger actual, String message)91     private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception {
92         if (!expected.equals(actual.toBigInteger())) {
93             throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16));
94         }
95     }
96 
testValueOfPow52(int p5, int p2)97     private static void testValueOfPow52(int p5, int p2) throws Exception {
98         check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2),
99                 "valueOfPow52(" + p5 + "," + p2 + ")");
100     }
101 
testValueOfPow52()102     private static void testValueOfPow52() throws Exception {
103         for (int p5 = 0; p5 <= MAX_P5; p5++) {
104             for (int p2 = 0; p2 <= MAX_P2; p2++) {
105                 testValueOfPow52(p5, p2);
106             }
107         }
108     }
109 
testValueOfMulPow52(long value, int p5, int p2)110     private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception {
111         BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK);
112         if (value < 0) {
113             bi = bi.setBit(63);
114         }
115         check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2),
116                 "valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")");
117     }
118 
testValueOfMulPow52(long value, int p5)119     private static void testValueOfMulPow52(long value, int p5) throws Exception {
120         testValueOfMulPow52(value, p5, 0);
121         testValueOfMulPow52(value, p5, 1);
122         testValueOfMulPow52(value, p5, 30);
123         testValueOfMulPow52(value, p5, 31);
124         testValueOfMulPow52(value, p5, 33);
125         testValueOfMulPow52(value, p5, 63);
126     }
127 
testValueOfMulPow52()128     private static void testValueOfMulPow52() throws Exception {
129         for (int p5 = 0; p5 <= MAX_P5; p5++) {
130             testValueOfMulPow52(0xFFFFFFFFL, p5);
131             testValueOfMulPow52(0x123456789AL, p5);
132             testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5);
133             testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5);
134         }
135     }
136 
testLeftShift(FDBigInteger t, int shift, boolean isImmutable)137     private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception {
138         BigInteger bt = t.toBigInteger();
139         FDBigInteger r = t.leftShift(shift);
140         if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) {
141             throw new Exception("leftShift doesn't reuse its argument");
142         }
143         if (isImmutable) {
144             check(bt, t, "leftShift corrupts its argument");
145         }
146         check(bt.shiftLeft(shift), r, "leftShift returns wrong result");
147     }
148 
testLeftShift()149     private static void testLeftShift() throws Exception {
150         testLeftShift(IMMUTABLE_ZERO, 0, true);
151         testLeftShift(IMMUTABLE_ZERO, 10, true);
152         testLeftShift(MUTABLE_ZERO, 0, false);
153         testLeftShift(MUTABLE_ZERO, 10, false);
154 
155         testLeftShift(IMMUTABLE_MILLION, 0, true);
156         testLeftShift(IMMUTABLE_MILLION, 1, true);
157         testLeftShift(IMMUTABLE_MILLION, 12, true);
158         testLeftShift(IMMUTABLE_MILLION, 13, true);
159         testLeftShift(IMMUTABLE_MILLION, 32, true);
160         testLeftShift(IMMUTABLE_MILLION, 33, true);
161         testLeftShift(IMMUTABLE_MILLION, 44, true);
162         testLeftShift(IMMUTABLE_MILLION, 45, true);
163 
164         testLeftShift(genMillion1(), 0, false);
165         testLeftShift(genMillion1(), 1, false);
166         testLeftShift(genMillion1(), 12, false);
167         testLeftShift(genMillion1(), 13, false);
168         testLeftShift(genMillion1(), 25, false);
169         testLeftShift(genMillion1(), 26, false);
170         testLeftShift(genMillion1(), 32, false);
171         testLeftShift(genMillion1(), 33, false);
172         testLeftShift(genMillion1(), 44, false);
173         testLeftShift(genMillion1(), 45, false);
174 
175         testLeftShift(genMillion2(), 0, false);
176         testLeftShift(genMillion2(), 1, false);
177         testLeftShift(genMillion2(), 12, false);
178         testLeftShift(genMillion2(), 13, false);
179         testLeftShift(genMillion2(), 25, false);
180         testLeftShift(genMillion2(), 26, false);
181         testLeftShift(genMillion2(), 32, false);
182         testLeftShift(genMillion2(), 33, false);
183         testLeftShift(genMillion2(), 44, false);
184         testLeftShift(genMillion2(), 45, false);
185     }
186 
testQuoRemIteration(FDBigInteger t, FDBigInteger s)187     private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception {
188         BigInteger bt = t.toBigInteger();
189         BigInteger bs = s.toBigInteger();
190         int q = t.quoRemIteration(s);
191         BigInteger[] qr = bt.divideAndRemainder(bs);
192         if (!BigInteger.valueOf(q).equals(qr[0])) {
193             throw new Exception("quoRemIteration returns incorrect quo");
194         }
195         check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem");
196     }
197 
testQuoRemIteration()198     private static void testQuoRemIteration() throws Exception {
199         // IMMUTABLE_TEN18 == 0de0b6b3a7640000
200         // q = 0
201         testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18);
202         testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18);
203         testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18);
204         // q = 1 -> q = 0
205         testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18);
206         testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18);
207         // q = 1
208         testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18);
209         testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18);
210         testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18);
211         testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18);
212         testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18);
213         // q = 18
214         testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18);
215     }
216 
testCmp(FDBigInteger t, FDBigInteger o)217     private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception {
218         BigInteger bt = t.toBigInteger();
219         BigInteger bo = o.toBigInteger();
220         int cmp = t.cmp(o);
221         int bcmp = bt.compareTo(bo);
222         if (bcmp != cmp) {
223             throw new Exception("cmp returns " + cmp + " expected " + bcmp);
224         }
225         check(bt, t, "cmp corrupts this");
226         check(bo, o, "cmp corrupts other");
227         if (o.cmp(t) != -cmp) {
228             throw new Exception("asymmetrical cmp");
229         }
230         check(bt, t, "cmp corrupts this");
231         check(bo, o, "cmp corrupts other");
232     }
233 
testCmp()234     private static void testCmp() throws Exception {
235         testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0));
236         testCmp(mutable("FFFFFFFF", 0), mutable("1", 1));
237         testCmp(mutable("5", 0), mutable("6", 0));
238         testCmp(mutable("5", 0), mutable("5", 0));
239         testCmp(mutable("5000000001", 0), mutable("500000001", 0));
240         testCmp(mutable("5000000001", 0), mutable("6", 1));
241         testCmp(mutable("5000000001", 0), mutable("5", 1));
242         testCmp(mutable("5000000000", 0), mutable("5", 1));
243     }
244 
testCmpPow52(FDBigInteger t, int p5, int p2)245     private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception {
246         FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2);
247         BigInteger bt = t.toBigInteger();
248         BigInteger bo = biPow52(p5, p2);
249         int cmp = t.cmp(o);
250         int bcmp = bt.compareTo(bo);
251         if (bcmp != cmp) {
252             throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp);
253         }
254         check(bt, t, "cmpPow52 corrupts this");
255         check(bo, o, "cmpPow5 corrupts other");
256     }
257 
testCmpPow52()258     private static void testCmpPow52() throws Exception {
259         testCmpPow52(mutable("00000002", 1), 0, 31);
260         testCmpPow52(mutable("00000002", 1), 0, 32);
261         testCmpPow52(mutable("00000002", 1), 0, 33);
262         testCmpPow52(mutable("00000002", 1), 0, 34);
263         testCmpPow52(mutable("00000002", 1), 0, 64);
264         testCmpPow52(mutable("00000003", 1), 0, 32);
265         testCmpPow52(mutable("00000003", 1), 0, 33);
266         testCmpPow52(mutable("00000003", 1), 0, 34);
267     }
268 
testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y)269     private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception {
270         BigInteger bt = t.toBigInteger();
271         BigInteger bx = x.toBigInteger();
272         BigInteger by = y.toBigInteger();
273         int cmp = t.addAndCmp(x, y);
274         int bcmp = bt.compareTo(bx.add(by));
275         if (bcmp != cmp) {
276             throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp);
277         }
278         check(bt, t, "addAndCmp corrupts this");
279         check(bx, x, "addAndCmp corrupts x");
280         check(by, y, "addAndCmp corrupts y");
281     }
282 
testAddAndCmp()283     private static void testAddAndCmp() throws Exception {
284         testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO);
285         testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO);
286         testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO);
287         testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0));
288         testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO);
289         testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0));
290         testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0));
291         testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0));
292 
293         testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1));
294         testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1));
295 
296         testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
297         testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
298         testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
299         testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
300 
301         testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
302         testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0));
303         testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
304         testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
305     }
306 
testMultBy10(FDBigInteger t, boolean isImmutable)307     private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception {
308         BigInteger bt = t.toBigInteger();
309         FDBigInteger r = t.multBy10();
310         if ((bt.signum() == 0 || !isImmutable) && r != t) {
311             throw new Exception("multBy10 of doesn't reuse its argument");
312         }
313         if (isImmutable) {
314             check(bt, t, "multBy10 corrupts its argument");
315         }
316         check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result");
317     }
318 
testMultBy10()319     private static void testMultBy10() throws Exception {
320         for (int p5 = 0; p5 <= MAX_P5; p5++) {
321             for (int p2 = 0; p2 <= MAX_P2; p2++) {
322                 // This strange way of creating a value ensures that it is mutable.
323                 FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
324                 testMultBy10(value, false);
325                 value.makeImmutable();
326                 testMultBy10(value, true);
327             }
328         }
329     }
330 
testMultByPow52(FDBigInteger t, int p5, int p2)331     private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception {
332         BigInteger bt = t.toBigInteger();
333         FDBigInteger r = t.multByPow52(p5, p2);
334         if (bt.signum() == 0 && r != t) {
335             throw new Exception("multByPow52 of doesn't reuse its argument");
336         }
337         check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result");
338     }
339 
testMultByPow52()340     private static void testMultByPow52() throws Exception {
341         for (int p5 = 0; p5 <= MAX_P5; p5++) {
342             for (int p2 = 0; p2 <= MAX_P2; p2++) {
343                 // This strange way of creating a value ensures that it is mutable.
344                 FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
345                 testMultByPow52(value, p5, p2);
346             }
347         }
348     }
349 
testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable)350     private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
351         BigInteger biLeft = left.toBigInteger();
352         BigInteger biRight = right.toBigInteger();
353         FDBigInteger diff = left.leftInplaceSub(right);
354         if (!isImmutable && diff != left) {
355             throw new Exception("leftInplaceSub of doesn't reuse its argument");
356         }
357         if (isImmutable) {
358             check(biLeft, left, "leftInplaceSub corrupts its left immutable argument");
359         }
360         check(biRight, right, "leftInplaceSub corrupts its right argument");
361         check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result");
362     }
363 
testLeftInplaceSub()364     private static void testLeftInplaceSub() throws Exception {
365         for (int p5 = 0; p5 <= MAX_P5; p5++) {
366             for (int p2 = 0; p2 <= MAX_P2; p2++) {
367 //                for (int p5r = 0; p5r <= p5; p5r += 10) {
368 //                    for (int p2r = 0; p2r <= p2; p2r += 10) {
369                 for (int p5r = 0; p5r <= p5; p5r++) {
370                     for (int p2r = 0; p2r <= p2; p2r++) {
371                         // This strange way of creating a value ensures that it is mutable.
372                         FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
373                         FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
374                         testLeftInplaceSub(left, right, false);
375                         left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
376                         left.makeImmutable();
377                         testLeftInplaceSub(left, right, true);
378                     }
379                 }
380             }
381         }
382     }
383 
testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable)384     private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
385         BigInteger biLeft = left.toBigInteger();
386         BigInteger biRight = right.toBigInteger();
387         FDBigInteger diff = left.rightInplaceSub(right);
388         if (!isImmutable && diff != right) {
389             throw new Exception("rightInplaceSub of doesn't reuse its argument");
390         }
391         check(biLeft, left, "leftInplaceSub corrupts its left argument");
392         if (isImmutable) {
393             check(biRight, right, "leftInplaceSub corrupts its right immutable argument");
394         }
395         try {
396             check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result");
397         } catch (Exception e) {
398             System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight));
399             throw e;
400         }
401     }
402 
testRightInplaceSub()403     private static void testRightInplaceSub() throws Exception {
404         for (int p5 = 0; p5 <= MAX_P5; p5++) {
405             for (int p2 = 0; p2 <= MAX_P2; p2++) {
406 //                for (int p5r = 0; p5r <= p5; p5r += 10) {
407 //                    for (int p2r = 0; p2r <= p2; p2r += 10) {
408                 for (int p5r = 0; p5r <= p5; p5r++) {
409                     for (int p2r = 0; p2r <= p2; p2r++) {
410                         // This strange way of creating a value ensures that it is mutable.
411                         FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
412                         FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
413                         testRightInplaceSub(left, right, false);
414                         right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
415                         right.makeImmutable();
416                         testRightInplaceSub(left, right, true);
417                     }
418                 }
419             }
420         }
421     }
422 
main(String[] args)423     public static void main(String[] args) throws Exception {
424         testValueOfPow52();
425         testValueOfMulPow52();
426         testLeftShift();
427         testQuoRemIteration();
428         testCmp();
429         testCmpPow52();
430         testAddAndCmp();
431         // Uncomment the following for more comprehensize but slow testing.
432         // testLeftInplaceSub();
433         // testMultBy10();
434         // testMultByPow52();
435         // testRightInplaceSub();
436     }
437 }
438