1 /* 2 * Copyright (c) 2009, 2012, 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 27 * @summary Basic tests for unsigned operations 28 * @author Joseph D. Darcy 29 */ 30 31 import java.math.*; 32 33 public class Unsigned { 34 public static void main(String... args) { 35 int errors = 0; 36 37 errors += testRoundtrip(); 38 errors += testByteToUnsignedLong(); 39 errors += testShortToUnsignedLong(); 40 errors += testUnsignedCompare(); 41 errors += testToStringUnsigned(); 42 errors += testParseUnsignedLong(); 43 errors += testDivideAndRemainder(); 44 45 if (errors > 0) { 46 throw new RuntimeException(errors + " errors found in unsigned operations."); 47 } 48 } 49 50 private static final BigInteger TWO = BigInteger.valueOf(2L); 51 52 private static int testRoundtrip() { 53 int errors = 0; 54 55 long[] data = {-1L, 0L, 1L}; 56 57 for(long datum : data) { 58 if (Long.parseUnsignedLong(Long.toBinaryString(datum), 2) != datum) { 59 errors++; 60 System.err.println("Bad binary roundtrip conversion of " + datum); 61 } 62 63 if (Long.parseUnsignedLong(Long.toOctalString(datum), 8) != datum) { 64 errors++; 65 System.err.println("Bad octal roundtrip conversion of " + datum); 66 } 67 68 if (Long.parseUnsignedLong(Long.toHexString(datum), 16) != datum) { 69 errors++; 70 System.err.println("Bad hex roundtrip conversion of " + datum); 71 } 72 } 73 return errors; 74 } 75 76 private static int testByteToUnsignedLong() { 77 int errors = 0; 78 79 for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { 80 byte datum = (byte) i; 81 long ui = Byte.toUnsignedLong(datum); 82 83 if ( (ui & (~0xffL)) != 0L || 84 ((byte)ui != datum )) { 85 errors++; 86 System.err.printf("Bad conversion of byte %d to unsigned long %d%n", 87 datum, ui); 88 } 89 } 90 return errors; 91 } 92 93 private static int testShortToUnsignedLong() { 94 int errors = 0; 95 96 for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) { 97 short datum = (short) i; 98 long ui = Short.toUnsignedLong(datum); 99 100 if ( (ui & (~0xffffL)) != 0L || 101 ((short)ui != datum )) { 102 errors++; 103 System.err.printf("Bad conversion of short %d to unsigned long %d%n", 104 datum, ui); 105 } 106 } 107 return errors; 108 } 109 private static int testUnsignedCompare() { 110 int errors = 0; 111 112 long[] data = { 113 0L, 114 1L, 115 2L, 116 3L, 117 0x00000000_80000000L, 118 0x00000000_FFFFFFFFL, 119 0x00000001_00000000L, 120 0x80000000_00000000L, 121 0x80000000_00000001L, 122 0x80000000_00000002L, 123 0x80000000_00000003L, 124 0x80000000_80000000L, 125 0xFFFFFFFF_FFFFFFFEL, 126 0xFFFFFFFF_FFFFFFFFL, 127 }; 128 129 for(long i : data) { 130 for(long j : data) { 131 long libraryResult = Long.compareUnsigned(i, j); 132 long libraryResultRev = Long.compareUnsigned(j, i); 133 long localResult = compUnsigned(i, j); 134 135 if (i == j) { 136 if (libraryResult != 0) { 137 errors++; 138 System.err.printf("Value 0x%x did not compare as " + 139 "an unsigned equal to itself; got %d%n", 140 i, libraryResult); 141 } 142 } 143 144 if (Long.signum(libraryResult) != Long.signum(localResult)) { 145 errors++; 146 System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" + 147 "\texpected sign of %d, got %d%n", 148 i, j, localResult, libraryResult); 149 } 150 151 if (Long.signum(libraryResult) != 152 -Long.signum(libraryResultRev)) { 153 errors++; 154 System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" + 155 " for \t0x%x and 0x%x, computed %d and %d%n", 156 i, j, libraryResult, libraryResultRev); 157 } 158 } 159 } 160 161 return errors; 162 } 163 164 private static int compUnsigned(long x, long y) { 165 BigInteger big_x = toUnsignedBigInt(x); 166 BigInteger big_y = toUnsignedBigInt(y); 167 168 return big_x.compareTo(big_y); 169 } 170 171 private static BigInteger toUnsignedBigInt(long x) { 172 if (x >= 0) 173 return BigInteger.valueOf(x); 174 else { 175 int upper = (int)(((long)x) >> 32); 176 int lower = (int) x; 177 178 BigInteger bi = // (upper << 32) + lower 179 (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32). 180 add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); 181 182 // System.out.printf("%n\t%d%n\t%s%n", x, bi.toString()); 183 return bi; 184 } 185 } 186 187 private static int testToStringUnsigned() { 188 int errors = 0; 189 190 long[] data = { 191 0L, 192 1L, 193 2L, 194 3L, 195 99999L, 196 100000L, 197 999999L, 198 100000L, 199 999999999L, 200 1000000000L, 201 0x1234_5678L, 202 0x8000_0000L, 203 0x8000_0001L, 204 0x8000_0002L, 205 0x8000_0003L, 206 0x8765_4321L, 207 0xFFFF_FFFEL, 208 0xFFFF_FFFFL, 209 210 // Long-range values 211 999_999_999_999L, 212 1_000_000_000_000L, 213 214 999_999_999_999_999_999L, 215 1_000_000_000_000_000_000L, 216 217 0xFFFF_FFFF_FFFF_FFFEL, 218 0xFFFF_FFFF_FFFF_FFFFL, 219 }; 220 221 for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 222 for(long datum : data) { 223 String result1 = Long.toUnsignedString(datum, radix); 224 String result2 = toUnsignedBigInt(datum).toString(radix); 225 226 if (!result1.equals(result2)) { 227 errors++; 228 System.err.printf("Unexpected string difference converting 0x%x:" + 229 "\t%s %s%n", 230 datum, result1, result2); 231 } 232 233 if (radix == 10) { 234 String result3 = Long.toUnsignedString(datum); 235 if (!result2.equals(result3)) { 236 errors++; 237 System.err.printf("Unexpected string difference converting 0x%x:" + 238 "\t%s %s%n", 239 datum, result3, result2); 240 } 241 } 242 243 long parseResult = Long.parseUnsignedLong(result1, radix); 244 245 if (parseResult != datum) { 246 errors++; 247 System.err.printf("Bad roundtrip conversion of %d in base %d" + 248 "\tconverting back ''%s'' resulted in %d%n", 249 datum, radix, result1, parseResult); 250 } 251 } 252 } 253 254 return errors; 255 } 256 257 private static int testParseUnsignedLong() { 258 int errors = 0; 259 long maxUnsignedInt = Integer.toUnsignedLong(0xffff_ffff); 260 261 // Values include those between signed Long.MAX_VALUE and 262 // unsignted Long MAX_VALUE. 263 BigInteger[] inRange = { 264 BigInteger.valueOf(0L), 265 BigInteger.valueOf(1L), 266 BigInteger.valueOf(10L), 267 BigInteger.valueOf(2147483646L), // Integer.MAX_VALUE - 1 268 BigInteger.valueOf(2147483647L), // Integer.MAX_VALUE 269 BigInteger.valueOf(2147483648L), // Integer.MAX_VALUE + 1 270 271 BigInteger.valueOf(maxUnsignedInt - 1L), 272 BigInteger.valueOf(maxUnsignedInt), 273 274 BigInteger.valueOf(Long.MAX_VALUE - 1L), 275 BigInteger.valueOf(Long.MAX_VALUE), 276 BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE), 277 278 TWO.pow(64).subtract(BigInteger.ONE) 279 }; 280 281 for(BigInteger value : inRange) { 282 for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) { 283 String bigString = value.toString(radix); 284 long longResult = Long.parseUnsignedLong(bigString, radix); 285 286 if (!toUnsignedBigInt(longResult).equals(value)) { 287 errors++; 288 System.err.printf("Bad roundtrip conversion of %d in base %d" + 289 "\tconverting back ''%s'' resulted in %d%n", 290 value, radix, bigString, longResult); 291 } 292 } 293 } 294 295 String[] outOfRange = { 296 null, 297 "", 298 "-1", 299 TWO.pow(64).toString(), 300 }; 301 302 for(String s : outOfRange) { 303 try { 304 long result = Long.parseUnsignedLong(s); 305 errors++; // Should not reach here 306 System.err.printf("Unexpected got %d from an unsigned conversion of %s", 307 result, s); 308 } catch(NumberFormatException nfe) { 309 ; // Correct result 310 } 311 } 312 313 return errors; 314 } 315 316 private static int testDivideAndRemainder() { 317 int errors = 0; 318 long MAX_UNSIGNED_INT = Integer.toUnsignedLong(0xffff_ffff); 319 320 BigInteger[] inRange = { 321 BigInteger.valueOf(0L), 322 BigInteger.valueOf(1L), 323 BigInteger.valueOf(10L), 324 BigInteger.valueOf(2147483646L), // Integer.MAX_VALUE - 1 325 BigInteger.valueOf(2147483647L), // Integer.MAX_VALUE 326 BigInteger.valueOf(2147483648L), // Integer.MAX_VALUE + 1 327 328 BigInteger.valueOf(MAX_UNSIGNED_INT - 1L), 329 BigInteger.valueOf(MAX_UNSIGNED_INT), 330 331 BigInteger.valueOf(Long.MAX_VALUE - 1L), 332 BigInteger.valueOf(Long.MAX_VALUE), 333 BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE), 334 335 TWO.pow(64).subtract(BigInteger.ONE) 336 }; 337 338 for(BigInteger dividend : inRange) { 339 for(BigInteger divisor : inRange) { 340 long quotient; 341 BigInteger longQuotient; 342 343 long remainder; 344 BigInteger longRemainder; 345 346 if (divisor.equals(BigInteger.ZERO)) { 347 try { 348 quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue()); 349 errors++; 350 } catch(ArithmeticException ea) { 351 ; // Expected 352 } 353 354 try { 355 remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue()); 356 errors++; 357 } catch(ArithmeticException ea) { 358 ; // Expected 359 } 360 } else { 361 quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue()); 362 longQuotient = dividend.divide(divisor); 363 364 if (quotient != longQuotient.longValue()) { 365 errors++; 366 System.err.printf("Unexpected unsigned divide result %s on %s/%s%n", 367 Long.toUnsignedString(quotient), 368 Long.toUnsignedString(dividend.longValue()), 369 Long.toUnsignedString(divisor.longValue())); 370 } 371 372 remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue()); 373 longRemainder = dividend.remainder(divisor); 374 375 if (remainder != longRemainder.longValue()) { 376 errors++; 377 System.err.printf("Unexpected unsigned remainder result %s on %s%%%s%n", 378 Long.toUnsignedString(remainder), 379 Long.toUnsignedString(dividend.longValue()), 380 Long.toUnsignedString(divisor.longValue())); 381 } 382 } 383 } 384 } 385 386 return errors; 387 } 388 }