jdk/test/java/lang/Integer/Unsigned.java
changeset 11672 a5fa8c844b54
child 14856 92a1bcf46888
equal deleted inserted replaced
11671:60fdf1412864 11672:a5fa8c844b54
       
     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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any 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 }