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 
  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 
  44         if (errors > 0) {
  45             throw new RuntimeException(errors + " errors found in unsigned operations.");
  46         }
  47     }
  48 
  49     private static int testRoundtrip() {
  50         int errors = 0;
  51         
  52         long[] data = {-1L, 0L, 1L};
  53 
  54         for(long datum : data) {
  55             if (Long.parseUnsignedLong(Long.toBinaryString(datum), 2) != datum) {
  56                 errors++;
  57                 System.err.println("Bad binary roundtrip conversion of " + datum);
  58             }
  59 
  60             if (Long.parseUnsignedLong(Long.toOctalString(datum), 8) != datum) {
  61                 errors++;
  62                 System.err.println("Bad octal roundtrip conversion of " + datum);
  63             }
  64 
  65             if (Long.parseUnsignedLong(Long.toHexString(datum), 16) != datum) {
  66                 errors++;
  67                 System.err.println("Bad hex roundtrip conversion of " + datum);
  68             }
  69         }
  70         return errors;
  71     }
  72 
  73     private static int testByteToUnsignedLong() {
  74         int errors = 0;
  75 
  76         for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
  77             byte datum = (byte) i;
  78             long ui = Byte.toUnsignedLong(datum);
  79             
  80             if ( (ui & (~0xffL)) != 0L ||
  81                  ((byte)ui != datum )) {
  82                 errors++;
  83                 System.err.printf("Bad conversion of byte %d to unsigned long %d%n",
  84                                   datum, ui);
  85             }
  86         }
  87         return errors;
  88     }
  89 
  90     private static int testShortToUnsignedLong() {
  91         int errors = 0;
  92 
  93         for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) {
  94             short datum = (short) i;
  95             long ui = Short.toUnsignedLong(datum);
  96             
  97             if ( (ui & (~0xffffL)) != 0L ||
  98                  ((short)ui != datum )) {
  99                 errors++;
 100                 System.err.printf("Bad conversion of short %d to unsigned long %d%n",
 101                                   datum, ui);
 102             }
 103         }
 104         return errors;
 105     }
 106     private static int testUnsignedCompare() {
 107         int errors = 0;
 108         
 109         long[] data = {
 110             0L,
 111             1L,
 112             2L,
 113             3L,
 114             0x00000000_80000000L,
 115             0x00000000_FFFFFFFFL,
 116             0x00000001_00000000L,
 117             0x80000000_00000000L,
 118             0x80000000_00000001L,
 119             0x80000000_00000002L,
 120             0x80000000_00000003L,
 121             0x80000000_80000000L,
 122             0xFFFFFFFF_FFFFFFFEL,
 123             0xFFFFFFFF_FFFFFFFFL,
 124         };
 125 
 126         for(long i : data) {
 127             for(long j : data) {
 128                 long libraryResult    = Long.compareUnsigned(i, j);
 129                 long libraryResultRev = Long.compareUnsigned(j, i);
 130                 long localResult      = compUnsigned(i, j);
 131                 
 132                 if (i == j) {
 133                     if (libraryResult != 0) {
 134                         errors++;
 135                         System.err.printf("Value 0x%x did not compare as " +
 136                                           "an unsigned equal to itself; got %d%n",
 137                                           i, libraryResult);
 138                     }
 139                 }
 140 
 141                    if (Long.signum(libraryResult) != Long.signum(localResult)) {
 142                        errors++;
 143                        System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" +
 144                                          "\texpected sign of %d, got %d%n",
 145                                          i, j, localResult, libraryResult);
 146                    }
 147 
 148                 if (Long.signum(libraryResult) !=
 149                     -Long.signum(libraryResultRev)) {
 150                     errors++;
 151                     System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" +
 152                                       " for \t0x%x and 0x%x, computed %d and %d%n",
 153                                       i, j, libraryResult, libraryResultRev);
 154                 }
 155             }
 156         }
 157 
 158         return errors;
 159     }
 160 
 161     private static int compUnsigned(long x, long y) {
 162         BigInteger big_x = toUnsignedBigInt(x);
 163         BigInteger big_y = toUnsignedBigInt(y);
 164 
 165         return big_x.compareTo(big_y);
 166     }
 167 
 168     private static BigInteger toUnsignedBigInt(long x) {
 169         if (x >= 0)
 170             return BigInteger.valueOf(x);
 171         else {
 172             int upper = (int)(((long)x) >> 32);
 173             int lower = (int) x;
 174 
 175             BigInteger bi = // (upper << 32) + lower
 176                 (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
 177                 add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
 178 
 179             // System.out.printf("%n\t%d%n\t%s%n", x, bi.toString());
 180             return bi;
 181         }
 182     }
 183 
 184     private static int testToStringUnsigned() {
 185         int errors = 0;
 186 
 187         long[] data = {
 188             0L,
 189             1L,
 190             2L,
 191             3L,
 192             99999L,
 193             100000L,
 194             999999L,
 195             100000L,
 196             999999999L,
 197             1000000000L,
 198             0x1234_5678L,
 199             0x8000_0000L,
 200             0x8000_0001L,
 201             0x8000_0002L,
 202             0x8000_0003L,
 203             0x8765_4321L,
 204             0xFFFF_FFFEL,
 205             0xFFFF_FFFFL,
 206             
 207             // Long-range values
 208               999_999_999_999L,
 209             1_000_000_000_000L,
 210 
 211               999_999_999_999_999_999L,
 212             1_000_000_000_000_000_000L,
 213 
 214             0xFFFF_FFFF_FFFF_FFFEL,
 215             0xFFFF_FFFF_FFFF_FFFFL,
 216         };
 217 
 218         for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
 219             for(long datum : data) {
 220                 String result1 = Long.toUnsignedString(datum, radix);
 221                 String result2 = toUnsignedBigInt(datum).toString(radix);
 222 
 223                 if (!result1.equals(result2)) {
 224                     errors++;
 225                     System.err.printf("Unexpected string difference converting 0x%x:" +
 226                                       "\t%s %s%n",
 227                                       datum, result1, result2);
 228                 }
 229 
 230                 if (radix == 10) {
 231                     String result3 = Long.toUnsignedString(datum);
 232                     if (!result2.equals(result3)) {
 233                         errors++;
 234                         System.err.printf("Unexpected string difference converting 0x%x:" +
 235                                           "\t%s %s%n",
 236                                           datum, result3, result2);
 237                     }
 238                 }
 239 
 240                 long parseResult = Long.parseUnsignedLong(result1, radix);
 241 
 242                 if (parseResult != datum) {
 243                     errors++;
 244                         System.err.printf("Bad roundtrip conversion of %d in base %d" +
 245                                           "\tconverting back ''%s'' resulted in %d%n",
 246                                           datum, radix, result1,  parseResult);
 247                 }
 248             }
 249         }
 250 
 251         return errors;
 252     }
 253     private static int testParseUnsignedLong() {
 254         int errors = 0;
 255         long maxUnsignedInt = Integer.toUnsignedLong(0xffff_ffff);
 256 
 257         final BigInteger TWO = BigInteger.valueOf(2L);
 258 
 259         // Values include those between signed Long.MAX_VALUE and
 260         // unsignted Long MAX_VALUE.
 261         BigInteger[] inRange = {
 262             BigInteger.valueOf(0L),
 263             BigInteger.valueOf(1L),
 264             BigInteger.valueOf(10L),
 265             BigInteger.valueOf(2147483646L),   // Integer.MAX_VALUE - 1
 266             BigInteger.valueOf(2147483647L),   // Integer.MAX_VALUE
 267             BigInteger.valueOf(2147483648L),   // Integer.MAX_VALUE + 1
 268             
 269             BigInteger.valueOf(maxUnsignedInt - 1L),
 270             BigInteger.valueOf(maxUnsignedInt),
 271 
 272             BigInteger.valueOf(Long.MAX_VALUE - 1L),
 273             BigInteger.valueOf(Long.MAX_VALUE),
 274             BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE),
 275 
 276             TWO.pow(64).subtract(BigInteger.ONE)
 277         };
 278 
 279         for(BigInteger value : inRange) {
 280             for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
 281                 String bigString = value.toString(radix);
 282                 long longResult = Long.parseUnsignedLong(bigString, radix);
 283 
 284                 if (!toUnsignedBigInt(longResult).equals(value)) {
 285                     errors++;
 286                     System.err.printf("Bad roundtrip conversion of %d in base %d" +
 287                                       "\tconverting back ''%s'' resulted in %d%n",
 288                                       value, radix, bigString,  longResult);
 289                 }
 290             }
 291         }
 292 
 293         String[] outOfRange = {
 294             null,
 295             "",
 296             "-1",
 297             TWO.pow(64).toString(),
 298         };
 299 
 300         for(String s : outOfRange) {
 301             try {
 302                 long result = Long.parseUnsignedLong(s);
 303                 errors++; // Should not reach here
 304                 System.err.printf("Unexpected got %d from an unsigned conversion of %s",
 305                                   result, s);
 306             } catch(NumberFormatException nfe) {
 307                 ; // Correct result
 308             }
 309         }
 310 
 311         return errors;
 312     }
 313 }