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