1 /* 2 * Copyright (c) 2009, 2020, 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 4504839 4215269 6322074 8030814 27 * @summary Basic tests for unsigned operations 28 * @author Joseph D. Darcy 29 */ 30 package test.java.lang.Long; 31 32 // Android-added: support for wrapper to avoid d8 backporting of Integer.parseInt (b/215435867). 33 import java.lang.invoke.MethodHandle; 34 import java.lang.invoke.MethodHandles; 35 import java.lang.invoke.MethodType; 36 37 import java.math.*; 38 39 import org.testng.annotations.Test; 40 import org.testng.Assert; 41 42 public class Unsigned { main(String... args)43 public static void main(String... args) { 44 int errors = 0; 45 46 errors += testRoundtrip(); 47 errors += testByteToUnsignedLong(); 48 errors += testShortToUnsignedLong(); 49 errors += testUnsignedCompare(); 50 errors += testToStringUnsigned(); 51 errors += testParseUnsignedLong(); 52 errors += testDivideAndRemainder(); 53 54 if (errors > 0) { 55 throw new RuntimeException(errors + " errors found in unsigned operations."); 56 } 57 } 58 59 private static final BigInteger TWO = BigInteger.valueOf(2L); 60 testRoundtrip()61 private static int testRoundtrip() { 62 int errors = 0; 63 64 long[] data = {-1L, 0L, 1L}; 65 66 for(long datum : data) { 67 if (Long.parseUnsignedLong(Long.toBinaryString(datum), 2) != datum) { 68 errors++; 69 System.err.println("Bad binary roundtrip conversion of " + datum); 70 } 71 72 if (Long.parseUnsignedLong(Long.toOctalString(datum), 8) != datum) { 73 errors++; 74 System.err.println("Bad octal roundtrip conversion of " + datum); 75 } 76 77 if (Long.parseUnsignedLong(Long.toHexString(datum), 16) != datum) { 78 errors++; 79 System.err.println("Bad hex roundtrip conversion of " + datum); 80 } 81 } 82 return errors; 83 } 84 testByteToUnsignedLong()85 private static int testByteToUnsignedLong() { 86 int errors = 0; 87 88 for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { 89 byte datum = (byte) i; 90 long ui = Byte.toUnsignedLong(datum); 91 92 if ( (ui & (~0xffL)) != 0L || 93 ((byte)ui != datum )) { 94 errors++; 95 System.err.printf("Bad conversion of byte %d to unsigned long %d%n", 96 datum, ui); 97 } 98 } 99 return errors; 100 } 101 testShortToUnsignedLong()102 private static int testShortToUnsignedLong() { 103 int errors = 0; 104 105 for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) { 106 short datum = (short) i; 107 long ui = Short.toUnsignedLong(datum); 108 109 if ( (ui & (~0xffffL)) != 0L || 110 ((short)ui != datum )) { 111 errors++; 112 System.err.printf("Bad conversion of short %d to unsigned long %d%n", 113 datum, ui); 114 } 115 } 116 return errors; 117 } testUnsignedCompare()118 private static int testUnsignedCompare() { 119 int errors = 0; 120 121 long[] data = { 122 0L, 123 1L, 124 2L, 125 3L, 126 0x00000000_80000000L, 127 0x00000000_FFFFFFFFL, 128 0x00000001_00000000L, 129 0x80000000_00000000L, 130 0x80000000_00000001L, 131 0x80000000_00000002L, 132 0x80000000_00000003L, 133 0x80000000_80000000L, 134 0xFFFFFFFF_FFFFFFFEL, 135 0xFFFFFFFF_FFFFFFFFL, 136 }; 137 138 for(long i : data) { 139 for(long j : data) { 140 long libraryResult = Long.compareUnsigned(i, j); 141 long libraryResultRev = Long.compareUnsigned(j, i); 142 long localResult = compUnsigned(i, j); 143 144 if (i == j) { 145 if (libraryResult != 0) { 146 errors++; 147 System.err.printf("Value 0x%x did not compare as " + 148 "an unsigned equal to itself; got %d%n", 149 i, libraryResult); 150 } 151 } 152 153 if (Long.signum(libraryResult) != Long.signum(localResult)) { 154 errors++; 155 System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" + 156 "\texpected sign of %d, got %d%n", 157 i, j, localResult, libraryResult); 158 } 159 160 if (Long.signum(libraryResult) != 161 -Long.signum(libraryResultRev)) { 162 errors++; 163 System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" + 164 " for \t0x%x and 0x%x, computed %d and %d%n", 165 i, j, libraryResult, libraryResultRev); 166 } 167 } 168 } 169 170 return errors; 171 } 172 compUnsigned(long x, long y)173 private static int compUnsigned(long x, long y) { 174 BigInteger big_x = toUnsignedBigInt(x); 175 BigInteger big_y = toUnsignedBigInt(y); 176 177 return big_x.compareTo(big_y); 178 } 179 toUnsignedBigInt(long x)180 private static BigInteger toUnsignedBigInt(long x) { 181 if (x >= 0) 182 return BigInteger.valueOf(x); 183 else { 184 int upper = (int)(((long)x) >> 32); 185 int lower = (int) x; 186 187 BigInteger bi = // (upper << 32) + lower 188 (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32). 189 add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); 190 191 // System.out.printf("%n\t%d%n\t%s%n", x, bi.toString()); 192 return bi; 193 } 194 } 195 testToStringUnsigned()196 private static int testToStringUnsigned() { 197 int errors = 0; 198 199 long[] data = { 200 0L, 201 1L, 202 2L, 203 3L, 204 99999L, 205 100000L, 206 999999L, 207 100000L, 208 999999999L, 209 1000000000L, 210 0x1234_5678L, 211 0x8000_0000L, 212 0x8000_0001L, 213 0x8000_0002L, 214 0x8000_0003L, 215 0x8765_4321L, 216 0xFFFF_FFFEL, 217 0xFFFF_FFFFL, 218 219 // Long-range values 220 999_999_999_999L, 221 1_000_000_000_000L, 222 223 999_999_999_999_999_999L, 224 1_000_000_000_000_000_000L, 225 226 0xFFFF_FFFF_FFFF_FFFEL, 227 0xFFFF_FFFF_FFFF_FFFFL, 228 }; 229 230 for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 231 for(long datum : data) { 232 String result1 = Long.toUnsignedString(datum, radix); 233 String result2 = toUnsignedBigInt(datum).toString(radix); 234 235 if (!result1.equals(result2)) { 236 errors++; 237 System.err.printf("Unexpected string difference converting 0x%x:" + 238 "\t%s %s%n", 239 datum, result1, result2); 240 } 241 242 if (radix == 10) { 243 String result3 = Long.toUnsignedString(datum); 244 if (!result2.equals(result3)) { 245 errors++; 246 System.err.printf("Unexpected string difference converting 0x%x:" + 247 "\t%s %s%n", 248 datum, result3, result2); 249 } 250 } 251 252 long parseResult = Long.parseUnsignedLong(result1, radix); 253 254 if (parseResult != datum) { 255 errors++; 256 System.err.printf("Bad roundtrip conversion of %d in base %d" + 257 "\tconverting back ''%s'' resulted in %d%n", 258 datum, radix, result1, parseResult); 259 } 260 } 261 } 262 263 return errors; 264 } 265 testParseUnsignedLong()266 private static int testParseUnsignedLong() { 267 int errors = 0; 268 long maxUnsignedInt = Integer.toUnsignedLong(0xffff_ffff); 269 270 // Values include those between signed Long.MAX_VALUE and 271 // unsignted Long MAX_VALUE. 272 BigInteger[] inRange = { 273 BigInteger.valueOf(0L), 274 BigInteger.valueOf(1L), 275 BigInteger.valueOf(10L), 276 BigInteger.valueOf(2147483646L), // Integer.MAX_VALUE - 1 277 BigInteger.valueOf(2147483647L), // Integer.MAX_VALUE 278 BigInteger.valueOf(2147483648L), // Integer.MAX_VALUE + 1 279 280 BigInteger.valueOf(maxUnsignedInt - 1L), 281 BigInteger.valueOf(maxUnsignedInt), 282 283 BigInteger.valueOf(Long.MAX_VALUE - 1L), 284 BigInteger.valueOf(Long.MAX_VALUE), 285 BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE), 286 287 TWO.pow(64).subtract(BigInteger.ONE) 288 }; 289 290 for(BigInteger value : inRange) { 291 for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 292 String bigString = value.toString(radix); 293 long longResult = Long.parseUnsignedLong(bigString, radix); 294 295 if (!toUnsignedBigInt(longResult).equals(value)) { 296 errors++; 297 System.err.printf("Bad roundtrip conversion of %d in base %d" + 298 "\tconverting back ''%s'' resulted in %d%n", 299 value, radix, bigString, longResult); 300 } 301 302 // test offset based parse method 303 longResult = Long.parseUnsignedLong("prefix" + bigString + "suffix", "prefix".length(), 304 "prefix".length() + bigString.length(), radix); 305 306 if (!toUnsignedBigInt(longResult).equals(value)) { 307 errors++; 308 System.err.printf("Bad roundtrip conversion of %d in base %d" + 309 "\tconverting back ''%s'' resulted in %d%n", 310 value, radix, bigString, longResult); 311 } 312 } 313 } 314 315 String[] outOfRange = { 316 null, 317 "", 318 "-1", 319 TWO.pow(64).toString(), 320 }; 321 322 for(String s : outOfRange) { 323 try { 324 long result = Long.parseUnsignedLong(s); 325 errors++; // Should not reach here 326 System.err.printf("Unexpected got %d from an unsigned conversion of %s", 327 result, s); 328 } catch(NumberFormatException nfe) { 329 ; // Correct result 330 } 331 } 332 333 // test case known at one time to fail 334 errors += testUnsignedOverflow("1234567890abcdef1", 16, true); 335 336 // largest value with guard = 91 = 13*7; radix = 13 337 errors += testUnsignedOverflow("196a78a44c3bba320c", 13, false); 338 339 // smallest value with guard = 92 = 23*2*2; radix = 23 340 errors += testUnsignedOverflow("137060c6g1c1dg0", 23, false); 341 342 // guard in [92,98]: no overflow 343 344 // one less than smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33 345 // smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33 346 errors += testUnsignedOverflow("b1w8p7j5q9r6g", 33, true); 347 348 // test overflow of overflow 349 BigInteger maxUnsignedLong = 350 BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE); 351 for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 352 BigInteger quotient = maxUnsignedLong.divide(BigInteger.valueOf(radix)); 353 for (int addend = 2; addend <= radix; addend++) { 354 BigInteger b = quotient.multiply(BigInteger.valueOf(radix + addend)); 355 errors += testUnsignedOverflow(b.toString(radix), radix, b.compareTo(maxUnsignedLong) > 0); 356 } 357 } 358 359 return errors; 360 } 361 362 // test for missing or unexpected unsigned overflow exception testUnsignedOverflow(String s, int radix, boolean exception)363 private static int testUnsignedOverflow(String s, int radix, boolean exception) { 364 int errors = 0; 365 long result; 366 try { 367 result = Long.parseUnsignedLong(s, radix); 368 if (exception) { 369 System.err.printf("Unexpected result %d for Long.parseUnsignedLong(%s,%d)\n", 370 result, s, radix); 371 errors++; 372 } 373 } catch (NumberFormatException nfe) { 374 if (!exception) { 375 System.err.printf("Unexpected exception %s for Long.parseUnsignedLong(%s,%d)\n", 376 nfe.toString(), s, radix); 377 errors++; 378 } 379 } 380 return errors; 381 } 382 testDivideAndRemainder()383 private static int testDivideAndRemainder() { 384 int errors = 0; 385 long TWO_31 = 1L << Integer.SIZE - 1; 386 long TWO_32 = 1L << Integer.SIZE; 387 long TWO_33 = 1L << Integer.SIZE + 1; 388 BigInteger NINETEEN = BigInteger.valueOf(19L); 389 BigInteger TWO_63 = BigInteger.ONE.shiftLeft(Long.SIZE - 1); 390 BigInteger TWO_64 = BigInteger.ONE.shiftLeft(Long.SIZE); 391 392 BigInteger[] inRange = { 393 BigInteger.ZERO, 394 BigInteger.ONE, 395 BigInteger.TEN, 396 NINETEEN, 397 398 BigInteger.valueOf(TWO_31 - 19L), 399 BigInteger.valueOf(TWO_31 - 10L), 400 BigInteger.valueOf(TWO_31 - 1L), 401 BigInteger.valueOf(TWO_31), 402 BigInteger.valueOf(TWO_31 + 1L), 403 BigInteger.valueOf(TWO_31 + 10L), 404 BigInteger.valueOf(TWO_31 + 19L), 405 406 BigInteger.valueOf(TWO_32 - 19L), 407 BigInteger.valueOf(TWO_32 - 10L), 408 BigInteger.valueOf(TWO_32 - 1L), 409 BigInteger.valueOf(TWO_32), 410 BigInteger.valueOf(TWO_32 + 1L), 411 BigInteger.valueOf(TWO_32 + 10L), 412 BigInteger.valueOf(TWO_32 - 19L), 413 414 BigInteger.valueOf(TWO_33 - 19L), 415 BigInteger.valueOf(TWO_33 - 10L), 416 BigInteger.valueOf(TWO_33 - 1L), 417 BigInteger.valueOf(TWO_33), 418 BigInteger.valueOf(TWO_33 + 1L), 419 BigInteger.valueOf(TWO_33 + 10L), 420 BigInteger.valueOf(TWO_33 + 19L), 421 422 TWO_63.subtract(NINETEEN), 423 TWO_63.subtract(BigInteger.TEN), 424 TWO_63.subtract(BigInteger.ONE), 425 TWO_63, 426 TWO_63.add(BigInteger.ONE), 427 TWO_63.add(BigInteger.TEN), 428 TWO_63.add(NINETEEN), 429 430 TWO_64.subtract(NINETEEN), 431 TWO_64.subtract(BigInteger.TEN), 432 TWO_64.subtract(BigInteger.ONE), 433 }; 434 435 for(BigInteger dividend : inRange) { 436 for(BigInteger divisor : inRange) { 437 long quotient; 438 BigInteger longQuotient; 439 440 long remainder; 441 BigInteger longRemainder; 442 443 if (divisor.equals(BigInteger.ZERO)) { 444 try { 445 quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue()); 446 errors++; 447 } catch(ArithmeticException ea) { 448 ; // Expected 449 } 450 451 try { 452 remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue()); 453 errors++; 454 } catch(ArithmeticException ea) { 455 ; // Expected 456 } 457 } else { 458 quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue()); 459 longQuotient = dividend.divide(divisor); 460 461 if (quotient != longQuotient.longValue()) { 462 errors++; 463 System.err.printf("Unexpected unsigned divide result %s on %s/%s%n", 464 Long.toUnsignedString(quotient), 465 Long.toUnsignedString(dividend.longValue()), 466 Long.toUnsignedString(divisor.longValue())); 467 } 468 469 remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue()); 470 longRemainder = dividend.remainder(divisor); 471 472 if (remainder != longRemainder.longValue()) { 473 errors++; 474 System.err.printf("Unexpected unsigned remainder result %s on %s%%%s%n", 475 Long.toUnsignedString(remainder), 476 Long.toUnsignedString(dividend.longValue()), 477 Long.toUnsignedString(divisor.longValue())); 478 } 479 } 480 } 481 } 482 483 return errors; 484 } 485 } 486