• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009, 2020, 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 
24 /*
25  * @test
26  * @bug 4504839 4215269 6322074 8030814
27  * @summary Basic tests for unsigned operations
28  * @author Joseph D. Darcy
29  */
30 package test.java.lang.Long;
31 
32 // Android-added: support for wrapper to avoid d8 backporting of Integer.parseInt (b/215435867).
33 import java.lang.invoke.MethodHandle;
34 import java.lang.invoke.MethodHandles;
35 import java.lang.invoke.MethodType;
36 
37 import java.math.*;
38 
39 import org.testng.annotations.Test;
40 import org.testng.Assert;
41 
42 public class Unsigned {
main(String... args)43     public static void main(String... args) {
44         int errors = 0;
45 
46         errors += testRoundtrip();
47         errors += testByteToUnsignedLong();
48         errors += testShortToUnsignedLong();
49         errors += testUnsignedCompare();
50         errors += testToStringUnsigned();
51         errors += testParseUnsignedLong();
52         errors += testDivideAndRemainder();
53 
54         if (errors > 0) {
55             throw new RuntimeException(errors + " errors found in unsigned operations.");
56         }
57     }
58 
59     private static final BigInteger TWO = BigInteger.valueOf(2L);
60 
testRoundtrip()61     private static int testRoundtrip() {
62         int errors = 0;
63 
64         long[] data = {-1L, 0L, 1L};
65 
66         for(long datum : data) {
67             if (Long.parseUnsignedLong(Long.toBinaryString(datum), 2) != datum) {
68                 errors++;
69                 System.err.println("Bad binary roundtrip conversion of " + datum);
70             }
71 
72             if (Long.parseUnsignedLong(Long.toOctalString(datum), 8) != datum) {
73                 errors++;
74                 System.err.println("Bad octal roundtrip conversion of " + datum);
75             }
76 
77             if (Long.parseUnsignedLong(Long.toHexString(datum), 16) != datum) {
78                 errors++;
79                 System.err.println("Bad hex roundtrip conversion of " + datum);
80             }
81         }
82         return errors;
83     }
84 
testByteToUnsignedLong()85     private static int testByteToUnsignedLong() {
86         int errors = 0;
87 
88         for(int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) {
89             byte datum = (byte) i;
90             long ui = Byte.toUnsignedLong(datum);
91 
92             if ( (ui & (~0xffL)) != 0L ||
93                  ((byte)ui != datum )) {
94                 errors++;
95                 System.err.printf("Bad conversion of byte %d to unsigned long %d%n",
96                                   datum, ui);
97             }
98         }
99         return errors;
100     }
101 
testShortToUnsignedLong()102     private static int testShortToUnsignedLong() {
103         int errors = 0;
104 
105         for(int i = Short.MIN_VALUE; i <= Short.MAX_VALUE; i++) {
106             short datum = (short) i;
107             long ui = Short.toUnsignedLong(datum);
108 
109             if ( (ui & (~0xffffL)) != 0L ||
110                  ((short)ui != datum )) {
111                 errors++;
112                 System.err.printf("Bad conversion of short %d to unsigned long %d%n",
113                                   datum, ui);
114             }
115         }
116         return errors;
117     }
testUnsignedCompare()118     private static int testUnsignedCompare() {
119         int errors = 0;
120 
121         long[] data = {
122             0L,
123             1L,
124             2L,
125             3L,
126             0x00000000_80000000L,
127             0x00000000_FFFFFFFFL,
128             0x00000001_00000000L,
129             0x80000000_00000000L,
130             0x80000000_00000001L,
131             0x80000000_00000002L,
132             0x80000000_00000003L,
133             0x80000000_80000000L,
134             0xFFFFFFFF_FFFFFFFEL,
135             0xFFFFFFFF_FFFFFFFFL,
136         };
137 
138         for(long i : data) {
139             for(long j : data) {
140                 long libraryResult    = Long.compareUnsigned(i, j);
141                 long libraryResultRev = Long.compareUnsigned(j, i);
142                 long localResult      = compUnsigned(i, j);
143 
144                 if (i == j) {
145                     if (libraryResult != 0) {
146                         errors++;
147                         System.err.printf("Value 0x%x did not compare as " +
148                                           "an unsigned equal to itself; got %d%n",
149                                           i, libraryResult);
150                     }
151                 }
152 
153                    if (Long.signum(libraryResult) != Long.signum(localResult)) {
154                        errors++;
155                        System.err.printf("Unsigned compare of 0x%x to 0x%x%n:" +
156                                          "\texpected sign of %d, got %d%n",
157                                          i, j, localResult, libraryResult);
158                    }
159 
160                 if (Long.signum(libraryResult) !=
161                     -Long.signum(libraryResultRev)) {
162                     errors++;
163                     System.err.printf("signum(compareUnsigned(x, y)) != -signum(compareUnsigned(y,x))" +
164                                       " for \t0x%x and 0x%x, computed %d and %d%n",
165                                       i, j, libraryResult, libraryResultRev);
166                 }
167             }
168         }
169 
170         return errors;
171     }
172 
compUnsigned(long x, long y)173     private static int compUnsigned(long x, long y) {
174         BigInteger big_x = toUnsignedBigInt(x);
175         BigInteger big_y = toUnsignedBigInt(y);
176 
177         return big_x.compareTo(big_y);
178     }
179 
toUnsignedBigInt(long x)180     private static BigInteger toUnsignedBigInt(long x) {
181         if (x >= 0)
182             return BigInteger.valueOf(x);
183         else {
184             int upper = (int)(((long)x) >> 32);
185             int lower = (int) x;
186 
187             BigInteger bi = // (upper << 32) + lower
188                 (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32).
189                 add(BigInteger.valueOf(Integer.toUnsignedLong(lower)));
190 
191             // System.out.printf("%n\t%d%n\t%s%n", x, bi.toString());
192             return bi;
193         }
194     }
195 
testToStringUnsigned()196     private static int testToStringUnsigned() {
197         int errors = 0;
198 
199         long[] data = {
200             0L,
201             1L,
202             2L,
203             3L,
204             99999L,
205             100000L,
206             999999L,
207             100000L,
208             999999999L,
209             1000000000L,
210             0x1234_5678L,
211             0x8000_0000L,
212             0x8000_0001L,
213             0x8000_0002L,
214             0x8000_0003L,
215             0x8765_4321L,
216             0xFFFF_FFFEL,
217             0xFFFF_FFFFL,
218 
219             // Long-range values
220               999_999_999_999L,
221             1_000_000_000_000L,
222 
223               999_999_999_999_999_999L,
224             1_000_000_000_000_000_000L,
225 
226             0xFFFF_FFFF_FFFF_FFFEL,
227             0xFFFF_FFFF_FFFF_FFFFL,
228         };
229 
230         for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
231             for(long datum : data) {
232                 String result1 = Long.toUnsignedString(datum, radix);
233                 String result2 = toUnsignedBigInt(datum).toString(radix);
234 
235                 if (!result1.equals(result2)) {
236                     errors++;
237                     System.err.printf("Unexpected string difference converting 0x%x:" +
238                                       "\t%s %s%n",
239                                       datum, result1, result2);
240                 }
241 
242                 if (radix == 10) {
243                     String result3 = Long.toUnsignedString(datum);
244                     if (!result2.equals(result3)) {
245                         errors++;
246                         System.err.printf("Unexpected string difference converting 0x%x:" +
247                                           "\t%s %s%n",
248                                           datum, result3, result2);
249                     }
250                 }
251 
252                 long parseResult = Long.parseUnsignedLong(result1, radix);
253 
254                 if (parseResult != datum) {
255                     errors++;
256                         System.err.printf("Bad roundtrip conversion of %d in base %d" +
257                                           "\tconverting back ''%s'' resulted in %d%n",
258                                           datum, radix, result1,  parseResult);
259                 }
260             }
261         }
262 
263         return errors;
264     }
265 
testParseUnsignedLong()266     private static int testParseUnsignedLong() {
267         int errors = 0;
268         long maxUnsignedInt = Integer.toUnsignedLong(0xffff_ffff);
269 
270         // Values include those between signed Long.MAX_VALUE and
271         // unsignted Long MAX_VALUE.
272         BigInteger[] inRange = {
273             BigInteger.valueOf(0L),
274             BigInteger.valueOf(1L),
275             BigInteger.valueOf(10L),
276             BigInteger.valueOf(2147483646L),   // Integer.MAX_VALUE - 1
277             BigInteger.valueOf(2147483647L),   // Integer.MAX_VALUE
278             BigInteger.valueOf(2147483648L),   // Integer.MAX_VALUE + 1
279 
280             BigInteger.valueOf(maxUnsignedInt - 1L),
281             BigInteger.valueOf(maxUnsignedInt),
282 
283             BigInteger.valueOf(Long.MAX_VALUE - 1L),
284             BigInteger.valueOf(Long.MAX_VALUE),
285             BigInteger.valueOf(Long.MAX_VALUE).add(BigInteger.ONE),
286 
287             TWO.pow(64).subtract(BigInteger.ONE)
288         };
289 
290         for(BigInteger value : inRange) {
291             for(int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
292                 String bigString = value.toString(radix);
293                 long longResult = Long.parseUnsignedLong(bigString, radix);
294 
295                 if (!toUnsignedBigInt(longResult).equals(value)) {
296                     errors++;
297                     System.err.printf("Bad roundtrip conversion of %d in base %d" +
298                                       "\tconverting back ''%s'' resulted in %d%n",
299                                       value, radix, bigString,  longResult);
300                 }
301 
302                 // test offset based parse method
303                 longResult = Long.parseUnsignedLong("prefix" + bigString + "suffix", "prefix".length(),
304                         "prefix".length() + bigString.length(), radix);
305 
306                 if (!toUnsignedBigInt(longResult).equals(value)) {
307                     errors++;
308                     System.err.printf("Bad roundtrip conversion of %d in base %d" +
309                             "\tconverting back ''%s'' resulted in %d%n",
310                             value, radix, bigString,  longResult);
311                 }
312             }
313         }
314 
315         String[] outOfRange = {
316             null,
317             "",
318             "-1",
319             TWO.pow(64).toString(),
320         };
321 
322         for(String s : outOfRange) {
323             try {
324                 long result = Long.parseUnsignedLong(s);
325                 errors++; // Should not reach here
326                 System.err.printf("Unexpected got %d from an unsigned conversion of %s",
327                                   result, s);
328             } catch(NumberFormatException nfe) {
329                 ; // Correct result
330             }
331         }
332 
333         // test case known at one time to fail
334         errors += testUnsignedOverflow("1234567890abcdef1", 16, true);
335 
336         // largest value with guard = 91 = 13*7; radix = 13
337         errors += testUnsignedOverflow("196a78a44c3bba320c", 13, false);
338 
339         // smallest value with guard = 92 = 23*2*2; radix = 23
340         errors += testUnsignedOverflow("137060c6g1c1dg0", 23, false);
341 
342         // guard in [92,98]: no overflow
343 
344         // one less than smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33
345         // smallest guard value to overflow: guard = 99 = 11*3*3, radix = 33
346         errors += testUnsignedOverflow("b1w8p7j5q9r6g", 33, true);
347 
348         // test overflow of overflow
349         BigInteger maxUnsignedLong =
350                 BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE);
351         for (int radix = Character.MIN_RADIX; radix <= Character.MAX_RADIX; radix++) {
352             BigInteger quotient = maxUnsignedLong.divide(BigInteger.valueOf(radix));
353             for (int addend = 2; addend <= radix; addend++) {
354                 BigInteger b = quotient.multiply(BigInteger.valueOf(radix + addend));
355                 errors += testUnsignedOverflow(b.toString(radix), radix, b.compareTo(maxUnsignedLong) > 0);
356             }
357         }
358 
359         return errors;
360     }
361 
362     // test for missing or unexpected unsigned overflow exception
testUnsignedOverflow(String s, int radix, boolean exception)363     private static int testUnsignedOverflow(String s, int radix, boolean exception) {
364         int errors = 0;
365         long result;
366         try {
367             result = Long.parseUnsignedLong(s, radix);
368             if (exception) {
369                 System.err.printf("Unexpected result %d for Long.parseUnsignedLong(%s,%d)\n",
370                         result, s, radix);
371                 errors++;
372             }
373         } catch (NumberFormatException nfe) {
374             if (!exception) {
375                 System.err.printf("Unexpected exception %s for Long.parseUnsignedLong(%s,%d)\n",
376                         nfe.toString(), s, radix);
377                 errors++;
378             }
379         }
380         return errors;
381     }
382 
testDivideAndRemainder()383     private static int testDivideAndRemainder() {
384         int errors = 0;
385         long TWO_31 = 1L << Integer.SIZE - 1;
386         long TWO_32 = 1L << Integer.SIZE;
387         long TWO_33 = 1L << Integer.SIZE + 1;
388         BigInteger NINETEEN = BigInteger.valueOf(19L);
389         BigInteger TWO_63 = BigInteger.ONE.shiftLeft(Long.SIZE - 1);
390         BigInteger TWO_64 = BigInteger.ONE.shiftLeft(Long.SIZE);
391 
392         BigInteger[] inRange = {
393             BigInteger.ZERO,
394             BigInteger.ONE,
395             BigInteger.TEN,
396             NINETEEN,
397 
398             BigInteger.valueOf(TWO_31 - 19L),
399             BigInteger.valueOf(TWO_31 - 10L),
400             BigInteger.valueOf(TWO_31 - 1L),
401             BigInteger.valueOf(TWO_31),
402             BigInteger.valueOf(TWO_31 + 1L),
403             BigInteger.valueOf(TWO_31 + 10L),
404             BigInteger.valueOf(TWO_31 + 19L),
405 
406             BigInteger.valueOf(TWO_32 - 19L),
407             BigInteger.valueOf(TWO_32 - 10L),
408             BigInteger.valueOf(TWO_32 - 1L),
409             BigInteger.valueOf(TWO_32),
410             BigInteger.valueOf(TWO_32 + 1L),
411             BigInteger.valueOf(TWO_32 + 10L),
412             BigInteger.valueOf(TWO_32 - 19L),
413 
414             BigInteger.valueOf(TWO_33 - 19L),
415             BigInteger.valueOf(TWO_33 - 10L),
416             BigInteger.valueOf(TWO_33 - 1L),
417             BigInteger.valueOf(TWO_33),
418             BigInteger.valueOf(TWO_33 + 1L),
419             BigInteger.valueOf(TWO_33 + 10L),
420             BigInteger.valueOf(TWO_33 + 19L),
421 
422             TWO_63.subtract(NINETEEN),
423             TWO_63.subtract(BigInteger.TEN),
424             TWO_63.subtract(BigInteger.ONE),
425             TWO_63,
426             TWO_63.add(BigInteger.ONE),
427             TWO_63.add(BigInteger.TEN),
428             TWO_63.add(NINETEEN),
429 
430             TWO_64.subtract(NINETEEN),
431             TWO_64.subtract(BigInteger.TEN),
432             TWO_64.subtract(BigInteger.ONE),
433         };
434 
435         for(BigInteger dividend : inRange) {
436             for(BigInteger divisor : inRange) {
437                 long quotient;
438                 BigInteger longQuotient;
439 
440                 long remainder;
441                 BigInteger longRemainder;
442 
443                 if (divisor.equals(BigInteger.ZERO)) {
444                     try {
445                         quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue());
446                         errors++;
447                     } catch(ArithmeticException ea) {
448                         ; // Expected
449                     }
450 
451                     try {
452                         remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue());
453                         errors++;
454                     } catch(ArithmeticException ea) {
455                         ; // Expected
456                     }
457                 } else {
458                     quotient = Long.divideUnsigned(dividend.longValue(), divisor.longValue());
459                     longQuotient = dividend.divide(divisor);
460 
461                     if (quotient != longQuotient.longValue()) {
462                         errors++;
463                         System.err.printf("Unexpected unsigned divide result %s on %s/%s%n",
464                                           Long.toUnsignedString(quotient),
465                                           Long.toUnsignedString(dividend.longValue()),
466                                           Long.toUnsignedString(divisor.longValue()));
467                     }
468 
469                     remainder = Long.remainderUnsigned(dividend.longValue(), divisor.longValue());
470                     longRemainder = dividend.remainder(divisor);
471 
472                     if (remainder != longRemainder.longValue()) {
473                         errors++;
474                         System.err.printf("Unexpected unsigned remainder result %s on %s%%%s%n",
475                                           Long.toUnsignedString(remainder),
476                                           Long.toUnsignedString(dividend.longValue()),
477                                           Long.toUnsignedString(divisor.longValue()));
478                     }
479                 }
480             }
481         }
482 
483         return errors;
484     }
485 }
486