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