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