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