1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  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
  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 += testUnsignedCompare();
  35         errors += testToUnsignedLong();
  36         errors += testToStringUnsigned();
  37         errors += testParseUnsignedInt();
  38 
  39         if (errors > 0) {
  40             throw new RuntimeException("Errors found in unsigned operations.");
  41         }
  42     }
  43 
  44     private static int testUnsignedCompare() {
  45         int errors = 0;
  46         
  47         int[] data = {
  48             0,
  49             1,
  50             2,
  51             3,
  52             0x8000_0000,
  53             0x8000_0001,
  54             0x8000_0002,
  55             0x8000_0003,
  56             0xFFFF_FFFE,
  57             0xFFFF_FFFF,
  58         };
  59 
  60         for(int i : data) {
  61             for(int j : data) {
  62                 int libraryResult    = Integer.compareUnsigned(i, j);
  63                 int libraryResultRev = Integer.compareUnsigned(j, i);
  64                 int localResult      = compUnsigned(i, j);
  65                 
  66                 if (i == j) {
  67                     if (libraryResult != 0) {
  68                         errors++;
  69                         System.err.printf("Value 0x%x did not compare as " +
  70                                           "an unsigned equal to itself; got %d%n",
  71                                           i, libraryResult);
  72                     }
  73                 }
  74 
  75                 if (Integer.signum(libraryResult) != Integer.signum(localResult)) {
  76                     errors++;
  77                     System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" +
  78                                       "\texpected sign of %d, got %d%n",
  79                                       i, j, localResult, libraryResult);
  80                 }
  81 
  82                 if (Integer.signum(libraryResult) !=
  83                     -Integer.signum(libraryResultRev)) {
  84                     errors++;
  85                     System.err.printf("unsgnCmp(x, y) != - unsignedComp(y,x) for" +
  86                                       "\t0x%x and 0x%x, computed %d and %d%n",
  87                                       i, j, libraryResult, libraryResultRev);
  88                 }
  89             }
  90         }
  91 
  92         return errors;
  93     }
  94 
  95     private static int compUnsigned(int x, int y) {
  96         int sign_x = x & Integer.MIN_VALUE;
  97         int sign_y = y & Integer.MIN_VALUE;
  98 
  99         int mant_x  = x & (~Integer.MIN_VALUE);
 100         int mant_y  = y & (~Integer.MIN_VALUE);
 101 
 102         if (sign_x == sign_y)
 103             return Integer.compare(mant_x, mant_y);
 104         else {
 105             if (sign_x == 0)
 106                 return -1; // sign x is 0, sign y is 1 => (x < y)
 107             else
 108                 return 1; //  sign x is 1, sign y is 0 => (x > y)
 109         }
 110     }
 111 
 112     private static int testToUnsignedLong() {
 113         int errors = 0;
 114 
 115         int[] data = {
 116             0,
 117             1,
 118             2,
 119             3,
 120             0x1234_5678,
 121             0x8000_0000,
 122             0x8000_0001,
 123             0x8000_0002,
 124             0x8000_0003,
 125             0x8765_4321,
 126             0xFFFF_FFFE,
 127             0xFFFF_FFFF,
 128         };
 129 
 130         for(int datum : data) {
 131             long result = Integer.toUnsignedLong(datum);
 132             
 133             // High-order bits should be zero
 134             if ((result & 0xffff_ffff_0000_0000L) != 0L) {
 135                 errors++;
 136                 System.err.printf("High bits set converting 0x%x to 0x%x%n",
 137                                   datum, result);
 138             }
 139 
 140             // Lower-order bits should be equal to datum.
 141             int lowOrder = (int)(result & 0x0000_0000_ffff_ffffL);
 142             if (lowOrder != datum ) {
 143                 errors++;
 144                 System.err.printf("Low bits not preserved converting 0x%x to 0x%x%n",
 145                                   datum, result);
 146             }
 147         }
 148         return errors;
 149     }
 150 
 151     private static int testToStringUnsigned() {
 152         int errors = 0;
 153 
 154         int[] data = {
 155             0,
 156             1,
 157             2,
 158             3,
 159             0x1234_5678,
 160             0x8000_0000,
 161             0x8000_0001,
 162             0x8000_0002,
 163             0x8000_0003,
 164             0x8765_4321,
 165             0xFFFF_FFFE,
 166             0xFFFF_FFFF,
 167         };
 168 
 169         for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
 170             for(int datum : data) {
 171                 String result1 = Integer.toUnsignedString(datum, radix);
 172                 String result2 = Long.toString(Integer.toUnsignedLong(datum), radix);
 173 
 174                 if (!result1.equals(result2)) {
 175                     errors++;
 176                     System.err.printf("Unexpected string difference converting 0x%x:" +
 177                                       "\t%s %s%n",
 178                                       datum, result1, result2);
 179                 }
 180 
 181                 if (radix == 10) {
 182                     String result3 = Integer.toUnsignedString(datum);
 183                     if (!result2.equals(result3)) {
 184                         errors++;
 185                         System.err.printf("Unexpected string difference converting 0x%x:" +
 186                                           "\t%s %s%n",
 187                                           datum, result3, result2);
 188                     }
 189                 }
 190 
 191                 int parseResult = Integer.parseUnsignedInt(result1, radix);
 192 
 193                 if (parseResult != datum) {
 194                     errors++;
 195                         System.err.printf("Bad roundtrip conversion of %d in base %d" +
 196                                           "\tconverting back ''%s'' resulted in %d%n",
 197                                           datum, radix, result1,  parseResult);
 198                 }
 199             }
 200         }
 201 
 202         return errors;
 203     }
 204 
 205 
 206     private static int testParseUnsignedInt() {
 207         int errors = 0;
 208         long maxUnsignedInt = Integer.toUnsignedLong(0xffff_ffff);
 209 
 210         // Values include those between signed Integer.MAX_VALUE and
 211         // unsignted int MAX_VALUE.
 212         long[] inRange = {
 213             2147483646L,   // MAX_VALUE - 1
 214             2147483647L,   // MAX_VALUE
 215             2147483648L,   // MAX_VALUE + 1
 216             
 217             maxUnsignedInt - 1L,
 218             maxUnsignedInt,
 219         };
 220 
 221         for(long value : inRange) {
 222             for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
 223                 String longString = Long.toString(value, radix);
 224                 int intResult = Integer.parseUnsignedInt(longString, radix);
 225 
 226                 if (Integer.toUnsignedLong(intResult) != value) {
 227                     errors++;
 228                     System.err.printf("Bad roundtrip conversion of %d in base %d" +
 229                                       "\tconverting back ''%s'' resulted in %d%n",
 230                                       value, radix, longString,  intResult);
 231                 }
 232             }
 233         }
 234 
 235         String[] outOfRange = {
 236             null,
 237             "",
 238             "-1",
 239             Long.toString(maxUnsignedInt + 1L),
 240             Long.toString(Long.MAX_VALUE)
 241         };
 242 
 243         for(String s : outOfRange) {
 244             try {
 245                 int result = Integer.parseUnsignedInt(s);
 246                 errors++; // Should not reach here
 247                 System.err.printf("Unexpected got %d from an unsigned conversion of %s",
 248                                   result, s);
 249             } catch(NumberFormatException nfe) {
 250                 ; // Correct result
 251             }
 252         }
 253         
 254         return errors;
 255     }
 256 }