--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Integer/Unsigned.java Tue Sep 12 19:03:39 2017 +0200
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 4504839 4215269 6322074
+ * @summary Basic tests for unsigned operations.
+ * @author Joseph D. Darcy
+ */
+public class Unsigned {
+ public static void main(String... args) {
+ int errors = 0;
+
+ errors += testRoundtrip();
+ errors += testByteToUnsignedInt();
+ errors += testShortToUnsignedInt();
+ errors += testUnsignedCompare();
+ errors += testToUnsignedLong();
+ errors += testToStringUnsigned();
+ errors += testParseUnsignedInt();
+ errors += testDivideAndRemainder();
+
+ if (errors > 0) {
+ throw new RuntimeException(errors + " errors found in unsigned operations.");
+ }
+ }
+
+ private static int testRoundtrip() {
+ int errors = 0;
+
+ int[] data = {-1, 0, 1};
+
+ for(int datum : data) {
+ if (Integer.parseUnsignedInt(Integer.toBinaryString(datum), 2) != datum) {
+ errors++;
+ System.err.println("Bad binary roundtrip conversion of " + datum);
+ }
+
+ if (Integer.parseUnsignedInt(Integer.toOctalString(datum), 8) != datum) {
+ errors++;
+ System.err.println("Bad octal roundtrip conversion of " + datum);
+ }
+
+ if (Integer.parseUnsignedInt(Integer.toHexString(datum), 16) != datum) {
+ errors++;
+ System.err.println("Bad hex roundtrip conversion of " + datum);
+ }
+ }
+ return errors;
+ }
+
+ private static int testByteToUnsignedInt() {
+ int errors = 0;
+
+ for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
+ byte datum = (byte) i;
+ int ui = Byte.toUnsignedInt(datum);
+
+ if ( (ui & (~0xff)) != 0 ||
+ ((byte)ui != datum )) {
+ errors++;
+ System.err.printf("Bad conversion of byte %d to unsigned int %d%n",
+ datum, ui);
+ }
+ }
+ return errors;
+ }
+
+ private static int testShortToUnsignedInt() {
+ int errors = 0;
+
+ for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) {
+ short datum = (short) i;
+ int ui = Short.toUnsignedInt(datum);
+
+ if ( (ui & (~0xffff)) != 0 ||
+ ((short)ui != datum )) {
+ errors++;
+ System.err.printf("Bad conversion of short %d to unsigned int %d%n",
+ datum, ui);
+ }
+ }
+ return errors;
+ }
+
+ private static int testUnsignedCompare() {
+ int errors = 0;
+
+ int[] data = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 0x8000_0000,
+ 0x8000_0001,
+ 0x8000_0002,
+ 0x8000_0003,
+ 0xFFFF_FFFE,
+ 0xFFFF_FFFF,
+ };
+
+ for(int i : data) {
+ for(int j : data) {
+ int libraryResult = Integer.compareUnsigned(i, j);
+ int libraryResultRev = Integer.compareUnsigned(j, i);
+ int localResult = compUnsigned(i, j);
+
+ if (i == j) {
+ if (libraryResult != 0) {
+ errors++;
+ System.err.printf("Value 0x%x did not compare as " +
+ "an unsigned value equal to itself; got %d%n",
+ i, libraryResult);
+ }
+ }
+
+ if (Integer.signum(libraryResult) != Integer.signum(localResult)) {
+ errors++;
+ System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" +
+ "\texpected sign of %d, got %d%n",
+ i, j, localResult, libraryResult);
+ }
+
+ if (Integer.signum(libraryResult) !=
+ -Integer.signum(libraryResultRev)) {
+ errors++;
+ System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" +
+ " for \t0x%x and 0x%x, computed %d and %d%n",
+ i, j, libraryResult, libraryResultRev);
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ /**
+ * Straightforward compare unsigned algorithm.
+ */
+ private static int compUnsigned(int x, int y) {
+ int sign_x = x & Integer.MIN_VALUE;
+ int sign_y = y & Integer.MIN_VALUE;
+
+ int mant_x = x & (~Integer.MIN_VALUE);
+ int mant_y = y & (~Integer.MIN_VALUE);
+
+ if (sign_x == sign_y)
+ return Integer.compare(mant_x, mant_y);
+ else {
+ if (sign_x == 0)
+ return -1; // sign x is 0, sign y is 1 => (x < y)
+ else
+ return 1; // sign x is 1, sign y is 0 => (x > y)
+ }
+ }
+
+ private static int testToUnsignedLong() {
+ int errors = 0;
+
+ int[] data = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 0x1234_5678,
+ 0x8000_0000,
+ 0x8000_0001,
+ 0x8000_0002,
+ 0x8000_0003,
+ 0x8765_4321,
+ 0xFFFF_FFFE,
+ 0xFFFF_FFFF,
+ };
+
+ for(int datum : data) {
+ long result = Integer.toUnsignedLong(datum);
+
+ // High-order bits should be zero
+ if ((result & 0xffff_ffff_0000_0000L) != 0L) {
+ errors++;
+ System.err.printf("High bits set converting 0x%x to 0x%x%n",
+ datum, result);
+ }
+
+ // Lower-order bits should be equal to datum.
+ int lowOrder = (int)(result & 0x0000_0000_ffff_ffffL);
+ if (lowOrder != datum ) {
+ errors++;
+ System.err.printf("Low bits not preserved converting 0x%x to 0x%x%n",
+ datum, result);
+ }
+ }
+ return errors;
+ }
+
+ private static int testToStringUnsigned() {
+ int errors = 0;
+
+ int[] data = {
+ 0,
+ 1,
+ 2,
+ 3,
+ 99999,
+ 100000,
+ 999999,
+ 100000,
+ 999999999,
+ 1000000000,
+ 0x1234_5678,
+ 0x8000_0000,
+ 0x8000_0001,
+ 0x8000_0002,
+ 0x8000_0003,
+ 0x8765_4321,
+ 0xFFFF_FFFE,
+ 0xFFFF_FFFF,
+ };
+
+ for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+ for(int datum : data) {
+ String result1 = Integer.toUnsignedString(datum, radix);
+ String result2 = Long.toString(Integer.toUnsignedLong(datum), radix);
+
+ if (!result1.equals(result2)) {
+ errors++;
+ System.err.printf("Unexpected string difference converting 0x%x:" +
+ "\t%s %s%n",
+ datum, result1, result2);
+ }
+
+ if (radix == 10) {
+ String result3 = Integer.toUnsignedString(datum);
+ if (!result2.equals(result3)) {
+ errors++;
+ System.err.printf("Unexpected string difference converting 0x%x:" +
+ "\t%s %s%n",
+ datum, result3, result2);
+ }
+ }
+
+ int parseResult = Integer.parseUnsignedInt(result1, radix);
+
+ if (parseResult != datum) {
+ errors++;
+ System.err.printf("Bad roundtrip conversion of %d in base %d" +
+ "\tconverting back ''%s'' resulted in %d%n",
+ datum, radix, result1, parseResult);
+ }
+ }
+ }
+
+ return errors;
+ }
+
+ private static final long MAX_UNSIGNED_INT = Integer.toUnsignedLong(0xffff_ffff);
+
+ private static int testParseUnsignedInt() {
+ int errors = 0;
+
+ // Values include those between signed Integer.MAX_VALUE and
+ // unsignted int MAX_VALUE.
+ long[] inRange = {
+ 0L,
+ 1L,
+ 10L,
+ 2147483646L, // MAX_VALUE - 1
+ 2147483647L, // MAX_VALUE
+ 2147483648L, // MAX_VALUE + 1
+
+ MAX_UNSIGNED_INT - 1L,
+ MAX_UNSIGNED_INT,
+ };
+
+ for(long value : inRange) {
+ for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
+ String longString = Long.toString(value, radix);
+ int intResult = Integer.parseUnsignedInt(longString, radix);
+
+ if (Integer.toUnsignedLong(intResult) != value) {
+ errors++;
+ System.err.printf("Bad roundtrip conversion of %d in base %d" +
+ "\tconverting back ''%s'' resulted in %d%n",
+ value, radix, longString, intResult);
+ }
+
+ // test offset based parse method
+ intResult = Integer.parseUnsignedInt("prefix" + longString + "suffix",
+ "prefix".length(), "prefix".length() + longString.length(), radix);
+
+ if (Integer.toUnsignedLong(intResult) != value) {
+ errors++;
+ System.err.printf("Bad roundtrip conversion of %d in base %d" +
+ "\tconverting back ''%s'' resulted in %d%n",
+ value, radix, longString, intResult);
+ }
+ }
+ }
+
+ String[] outOfRange = {
+ null,
+ "",
+ "-1",
+ Long.toString(MAX_UNSIGNED_INT + 1L),
+ Long.toString(Long.MAX_VALUE)
+ };
+
+ for(String s : outOfRange) {
+ try {
+ int result = Integer.parseUnsignedInt(s);
+ errors++; // Should not reach here
+ System.err.printf("Unexpected got %d from an unsigned conversion of %s",
+ result, s);
+ } catch(NumberFormatException nfe) {
+ ; // Correct result
+ }
+ }
+
+ return errors;
+ }
+
+ private static int testDivideAndRemainder() {
+ int errors = 0;
+
+ long[] inRange = {
+ 0L,
+ 1L,
+ 2L,
+ 2147483646L, // MAX_VALUE - 1
+ 2147483647L, // MAX_VALUE
+ 2147483648L, // MAX_VALUE + 1
+
+ MAX_UNSIGNED_INT - 1L,
+ MAX_UNSIGNED_INT,
+ };
+
+ for(long dividend : inRange) {
+ for(long divisor : inRange) {
+ int quotient;
+ long longQuotient;
+
+ int remainder;
+ long longRemainder;
+
+ if (divisor == 0) {
+ try {
+ quotient = Integer.divideUnsigned((int) dividend, (int) divisor);
+ errors++;
+ } catch(ArithmeticException ea) {
+ ; // Expected
+ }
+
+ try {
+ remainder = Integer.remainderUnsigned((int) dividend, (int) divisor);
+ errors++;
+ } catch(ArithmeticException ea) {
+ ; // Expected
+ }
+ } else {
+ quotient = Integer.divideUnsigned((int) dividend, (int) divisor);
+ longQuotient = dividend / divisor;
+
+ if (quotient != (int)longQuotient) {
+ errors++;
+ System.err.printf("Unexpected unsigned divide result %s on %s/%s%n",
+ Integer.toUnsignedString(quotient),
+ Integer.toUnsignedString((int) dividend),
+ Integer.toUnsignedString((int) divisor));
+ }
+
+ remainder = Integer.remainderUnsigned((int) dividend, (int) divisor);
+ longRemainder = dividend % divisor;
+
+ if (remainder != (int)longRemainder) {
+ errors++;
+ System.err.printf("Unexpected unsigned remainder result %s on %s%%%s%n",
+ Integer.toUnsignedString(remainder),
+ Integer.toUnsignedString((int) dividend),
+ Integer.toUnsignedString((int) divisor));
+ }
+ }
+ }
+ }
+
+ return errors;
+ }
+}