1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * Test arithmetic operations.
19  */
20 public class IntMath {
21 
shiftTest1()22     static void shiftTest1() {
23         System.out.println("IntMath.shiftTest1");
24 
25         final int[] mBytes = {
26             0x11, 0x22, 0x33, 0x44, 0x88, 0x99, 0xaa, 0xbb
27         };
28         long l;
29         int i1, i2;
30 
31         i1 = mBytes[0] | mBytes[1] << 8 | mBytes[2] << 16 | mBytes[3] << 24;
32         i2 = mBytes[4] | mBytes[5] << 8 | mBytes[6] << 16 | mBytes[7] << 24;
33         l = i1 | ((long)i2 << 32);
34 
35         Main.assertTrue(i1 == 0x44332211);
36         Main.assertTrue(i2 == 0xbbaa9988);
37         Main.assertTrue(l == 0xbbaa998844332211L);
38 
39         l = (long)mBytes[0]
40             | (long)mBytes[1] << 8
41             | (long)mBytes[2] << 16
42             | (long)mBytes[3] << 24
43             | (long)mBytes[4] << 32
44             | (long)mBytes[5] << 40
45             | (long)mBytes[6] << 48
46             | (long)mBytes[7] << 56;
47 
48         Main.assertTrue(l == 0xbbaa998844332211L);
49     }
50 
shiftTest2()51     static void shiftTest2() {
52         System.out.println("IntMath.shiftTest2");
53 
54         long    a = 0x11;
55         long    b = 0x22;
56         long    c = 0x33;
57         long    d = 0x44;
58         long    e = 0x55;
59         long    f = 0x66;
60         long    g = 0x77;
61         long    h = 0x88;
62 
63         long    result = ((a << 56) | (b << 48) | (c << 40) | (d << 32) |
64                          (e << 24) | (f << 16) | (g <<  8) | h);
65 
66         Main.assertTrue(result == 0x1122334455667788L);
67     }
68 
unsignedShiftTest()69     static void unsignedShiftTest() {
70         System.out.println("IntMath.unsignedShiftTest");
71 
72         byte b = -4;
73         short s = -4;
74         char c = 0xfffc;
75         int i = -4;
76 
77         b >>>= 4;
78         s >>>= 4;
79         c >>>= 4;
80         i >>>= 4;
81 
82         Main.assertTrue((int) b == -1);
83         Main.assertTrue((int) s == -1);
84         Main.assertTrue((int) c == 0x0fff);
85         Main.assertTrue(i == 268435455);
86     }
87 
shiftTest3(int thirtyTwo)88     static void shiftTest3(int thirtyTwo) {
89         System.out.println("IntMath.shiftTest3");
90 
91         int one = thirtyTwo / 32;
92         int sixteen = thirtyTwo / 2;
93         int thirtyThree = thirtyTwo + 1;
94         int sixtyFour = thirtyTwo * 2;
95 
96         Main.assertTrue(1 << thirtyTwo == 1);
97         Main.assertTrue((1 << sixteen) << sixteen == 0);
98         Main.assertTrue(1 << thirtyThree == 2);
99         Main.assertTrue(1 << -one == -2147483648);
100         Main.assertTrue(1 << -thirtyTwo == 1);
101         Main.assertTrue(1 << -thirtyThree == -2147483648);
102         Main.assertTrue(1 << thirtyThree == 2);
103 
104         Main.assertTrue(1 >> thirtyTwo == 1);
105         Main.assertTrue((1 >> sixteen) >> sixteen == 0);
106         Main.assertTrue(1 >> thirtyThree == 0);
107         Main.assertTrue(1 >> -one == 0);
108         Main.assertTrue(1 >> -thirtyTwo == 1);
109         Main.assertTrue(1 >> -thirtyThree == 0);
110         Main.assertTrue(-4 >> thirtyThree == -2);
111 
112         Main.assertTrue(1 >>> thirtyTwo == 1);
113         Main.assertTrue((1 >>> sixteen) >>> sixteen == 0);
114         Main.assertTrue(1 >>> thirtyThree == 0);
115         Main.assertTrue(1 >>> -one == 0);
116         Main.assertTrue(1 >>> -thirtyTwo == 1);
117         Main.assertTrue(1 >>> -thirtyThree == 0);
118         Main.assertTrue(-4 >>> thirtyThree == 2147483646);
119     }
120 
convTest()121     static void convTest() {
122         System.out.println("IntMath.convTest");
123 
124         float f;
125         double d;
126         int i;
127         long l;
128 
129         /* int --> long */
130         i = 7654;
131         l = (long) i;
132         Main.assertTrue(l == 7654L);
133 
134         i = -7654;
135         l = (long) i;
136         Main.assertTrue(l == -7654L);
137 
138         /* long --> int (with truncation) */
139         l = 5678956789L;
140         i = (int) l;
141         Main.assertTrue(i == 1383989493);
142 
143         l = -5678956789L;
144         i = (int) l;
145         Main.assertTrue(i == -1383989493);
146     }
147 
charSubTest()148     static void charSubTest() {
149         System.out.println("IntMath.charSubTest");
150 
151         char char1 = 0x00e9;
152         char char2 = 0xffff;
153         int i;
154 
155         /* chars are unsigned-expanded to ints before subtraction */
156         i = char1 - char2;
157         Main.assertTrue(i == 0xffff00ea);
158     }
159 
160     /*
161      * We pass in the arguments and return the results so the compiler
162      * doesn't do the math for us.  (x=70000, y=-3)
163      */
intOperTest(int x, int y)164     static int[] intOperTest(int x, int y) {
165         System.out.println("IntMath.intOperTest");
166 
167         int[] results = new int[10];
168 
169         /* this seems to generate "op-int" instructions */
170         results[0] = x + y;
171         results[1] = x - y;
172         results[2] = x * y;
173         results[3] = x * x;
174         results[4] = x / y;
175         results[5] = x % -y;
176         results[6] = x & y;
177         results[7] = x | y;
178         results[8] = x ^ y;
179 
180         /* this seems to generate "op-int/2addr" instructions */
181         results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y);
182 
183         return results;
184     }
intOperCheck(int[] results)185     static void intOperCheck(int[] results) {
186         System.out.println("IntMath.intOperCheck");
187 
188         /* check this edge case while we're here (div-int/2addr) */
189         int minInt = -2147483648;
190         int negOne = -results[5];
191         int plusOne = 1;
192         int result = (((minInt + plusOne) - plusOne) / negOne) / negOne;
193         Main.assertTrue(result == minInt);
194 
195         Main.assertTrue(results[0] == 69997);
196         Main.assertTrue(results[1] == 70003);
197         Main.assertTrue(results[2] == -210000);
198         Main.assertTrue(results[3] == 605032704);    // overflow / truncate
199         Main.assertTrue(results[4] == -23333);
200         Main.assertTrue(results[5] == 1);
201         Main.assertTrue(results[6] == 70000);
202         Main.assertTrue(results[7] == -3);
203         Main.assertTrue(results[8] == -70003);
204         Main.assertTrue(results[9] == 70000);
205     }
206 
207     /*
208      * More operations, this time with 16-bit constants.  (x=77777)
209      */
lit16Test(int x)210     static int[] lit16Test(int x) {
211         System.out.println("IntMath.lit16Test");
212 
213         int[] results = new int[8];
214 
215         /* try to generate op-int/lit16" instructions */
216         results[0] = x + 1000;
217         results[1] = 1000 - x;
218         results[2] = x * 1000;
219         results[3] = x / 1000;
220         results[4] = x % 1000;
221         results[5] = x & 1000;
222         results[6] = x | -1000;
223         results[7] = x ^ -1000;
224         return results;
225     }
lit16Check(int[] results)226     static void lit16Check(int[] results) {
227         Main.assertTrue(results[0] == 78777);
228         Main.assertTrue(results[1] == -76777);
229         Main.assertTrue(results[2] == 77777000);
230         Main.assertTrue(results[3] == 77);
231         Main.assertTrue(results[4] == 777);
232         Main.assertTrue(results[5] == 960);
233         Main.assertTrue(results[6] == -39);
234         Main.assertTrue(results[7] == -76855);
235     }
236 
237     /*
238      * More operations, this time with 8-bit constants.  (x=-55555)
239      */
lit8Test(int x)240     static int[] lit8Test(int x) {
241         System.out.println("IntMath.lit8Test");
242 
243         int[] results = new int[8];
244 
245         /* try to generate op-int/lit8" instructions */
246         results[0] = x + 10;
247         results[1] = 10 - x;
248         results[2] = x * 10;
249         results[3] = x / 10;
250         results[4] = x % 10;
251         results[5] = x & 10;
252         results[6] = x | -10;
253         results[7] = x ^ -10;
254         return results;
255     }
lit8Check(int[] results)256     static void lit8Check(int[] results) {
257         //for (int i = 0; i < results.length; i++)
258         //    System.out.println(" " + i + ": " + results[i]);
259 
260         /* check this edge case while we're here (div-int/lit8) */
261         int minInt = -2147483648;
262         int result = minInt / -1;
263         Main.assertTrue(result == minInt);
264 
265         Main.assertTrue(results[0] == -55545);
266         Main.assertTrue(results[1] == 55565);
267         Main.assertTrue(results[2] == -555550);
268         Main.assertTrue(results[3] == -5555);
269         Main.assertTrue(results[4] == -5);
270         Main.assertTrue(results[5] == 8);
271         Main.assertTrue(results[6] == -1);
272         Main.assertTrue(results[7] == 55563);
273     }
274 
275     /*
276      * Make sure special-cased literal division matches
277      * normal division.
278      */
divLiteralTestBody(int start, int count)279     static void divLiteralTestBody(int start, int count) {
280        int normal = 0;
281        int special = 0;
282        for (int i = 0; i < count; i++) {
283            for (int j = 3; j < 16; j++) {
284                switch(j) {
285                    case 3:
286                        normal = (start+i) / j;
287                        special = (start+i) / 3;
288                        break;
289                    case 4:
290                        normal = (start+i) / j;
291                        special = (start+i) / 4;
292                        break;
293                    case 5:
294                        normal = (start+i) / j;
295                        special = (start+i) / 5;
296                        break;
297                    case 6:
298                        normal = (start+i) / j;
299                        special = (start+i) / 6;
300                        break;
301                    case 7:
302                        normal = (start+i) / j;
303                        special = (start+i) / 7;
304                        break;
305                    case 8:
306                        normal = (start+i) / j;
307                        special = (start+i) / 8;
308                        break;
309                    case 9:
310                        normal = (start+i) / j;
311                        special = (start+i) / 9;
312                        break;
313                    case 10:
314                        normal = (start+i) / j;
315                        special = (start+i) / 10;
316                        break;
317                    case 11:
318                        normal = (start+i) / j;
319                        special = (start+i) / 11;
320                        break;
321                    case 12:
322                        normal = (start+i) / j;
323                        special = (start+i) / 12;
324                        break;
325                    case 13:
326                        normal = (start+i) / j;
327                        special = (start+i) / 13;
328                        break;
329                    case 14:
330                        normal = (start+i) / j;
331                        special = (start+i) / 14;
332                        break;
333                    case 15:
334                        normal = (start+i) / j;
335                        special = (start+i) / 15;
336                        break;
337                }
338                Main.assertTrue(normal == special);
339            }
340        }
341     }
342 
divLiteralTest()343     static void divLiteralTest() {
344        System.out.println("IntMath.divLiteralTest");
345        divLiteralTestBody(-1000, 2000);
346        divLiteralTestBody(0x7fffffff-2000, 2000);
347        divLiteralTestBody(0xfff0ffff, 2000);
348     }
349 
350     /*
351      * Shift some data.  (value=0xff00aa01, dist=8)
352      */
intShiftTest(int value, int dist)353     static int[] intShiftTest(int value, int dist) {
354         System.out.println("IntMath.intShiftTest");
355 
356         int results[] = new int[4];
357 
358         results[0] = value << dist;
359         results[1] = value >> dist;
360         results[2] = value >>> dist;
361 
362         results[3] = (((value << dist) >> dist) >>> dist) << dist;
363         return results;
364     }
intShiftCheck(int[] results)365     static void intShiftCheck(int[] results) {
366         System.out.println("IntMath.intShiftCheck");
367 
368         Main.assertTrue(results[0] == 0x00aa0100);
369         Main.assertTrue(results[1] == 0xffff00aa);
370         Main.assertTrue(results[2] == 0x00ff00aa);
371         Main.assertTrue(results[3] == 0xaa00);
372     }
373 
374     /*
375      * We pass in the arguments and return the results so the compiler
376      * doesn't do the math for us.  (x=70000000000, y=-3)
377      */
longOperTest(long x, long y)378     static long[] longOperTest(long x, long y) {
379         System.out.println("IntMath.longOperTest");
380 
381         long[] results = new long[10];
382 
383         /* this seems to generate "op-long" instructions */
384         results[0] = x + y;
385         results[1] = x - y;
386         results[2] = x * y;
387         results[3] = x * x;
388         results[4] = x / y;
389         results[5] = x % -y;
390         results[6] = x & y;
391         results[7] = x | y;
392         results[8] = x ^ y;
393 
394         /* this seems to generate "op-long/2addr" instructions */
395         results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y);
396 
397         return results;
398     }
longOperCheck(long[] results)399     static void longOperCheck(long[] results) {
400         System.out.println("IntMath.longOperCheck");
401 
402         /* check this edge case while we're here (div-long/2addr) */
403         long minLong = -9223372036854775808L;
404         long negOne = -results[5];
405         long plusOne = 1;
406         long result = (((minLong + plusOne) - plusOne) / negOne) / negOne;
407         Main.assertTrue(result == minLong);
408 
409         Main.assertTrue(results[0] == 69999999997L);
410         Main.assertTrue(results[1] == 70000000003L);
411         Main.assertTrue(results[2] == -210000000000L);
412         Main.assertTrue(results[3] == -6833923606740729856L);    // overflow
413         Main.assertTrue(results[4] == -23333333333L);
414         Main.assertTrue(results[5] == 1);
415         Main.assertTrue(results[6] == 70000000000L);
416         Main.assertTrue(results[7] == -3);
417         Main.assertTrue(results[8] == -70000000003L);
418         Main.assertTrue(results[9] == 70000000000L);
419 
420         Main.assertTrue(results.length == 10);
421     }
422 
423     /*
424      * Shift some data.  (value=0xd5aa96deff00aa01, dist=8)
425      */
longShiftTest(long value, int dist)426     static long[] longShiftTest(long value, int dist) {
427         System.out.println("IntMath.longShiftTest");
428 
429         long results[] = new long[4];
430 
431         results[0] = value << dist;
432         results[1] = value >> dist;
433         results[2] = value >>> dist;
434 
435         results[3] = (((value << dist) >> dist) >>> dist) << dist;
436         return results;
437     }
longShiftCheck(long[] results)438     static long longShiftCheck(long[] results) {
439         System.out.println("IntMath.longShiftCheck");
440 
441         Main.assertTrue(results[0] == 0x96deff00aa010000L);
442         Main.assertTrue(results[1] == 0xffffd5aa96deff00L);
443         Main.assertTrue(results[2] == 0x0000d5aa96deff00L);
444         Main.assertTrue(results[3] == 0xffff96deff000000L);
445 
446         Main.assertTrue(results.length == 4);
447 
448         return results[0];      // test return-long
449     }
450 
451 
452     /*
453      * Try to cause some unary operations.
454      */
unopTest(int x)455     static int unopTest(int x) {
456         x = -x;
457         x ^= 0xffffffff;
458         return x;
459     }
unopCheck(int result)460     static void unopCheck(int result) {
461         Main.assertTrue(result == 37);
462     }
463 
464     static class Shorty {
465         public short mShort;
466         public char mChar;
467         public byte mByte;
468     };
469 
470     /*
471      * Truncate an int.
472      */
truncateTest(int x)473     static Shorty truncateTest(int x) {
474         System.out.println("IntMath.truncateTest");
475         Shorty shorts = new Shorty();
476 
477         shorts.mShort = (short) x;
478         shorts.mChar = (char) x;
479         shorts.mByte = (byte) x;
480         return shorts;
481     }
truncateCheck(Shorty shorts)482     static void truncateCheck(Shorty shorts) {
483         Main.assertTrue(shorts.mShort == -5597);     // 0xea23
484         Main.assertTrue(shorts.mChar == 59939);      // 0xea23
485         Main.assertTrue(shorts.mByte == 35);         // 0x23
486     }
487 
488     /*
489      * Verify that we get a divide-by-zero exception.
490      */
divideByZero(int z)491     static void divideByZero(int z) {
492         System.out.println("IntMath.divideByZero");
493 
494         try {
495             int x = 100 / z;
496             Main.assertTrue(false);
497         } catch (ArithmeticException ae) {
498         }
499 
500         try {
501             int x = 100 % z;
502             Main.assertTrue(false);
503         } catch (ArithmeticException ae) {
504         }
505 
506         try {
507             long x = 100L / z;
508             Main.assertTrue(false);
509         } catch (ArithmeticException ae) {
510         }
511 
512         try {
513             long x = 100L % z;
514             Main.assertTrue(false);
515         } catch (ArithmeticException ae) {
516         }
517     }
518 
519     /*
520      * Check an edge condition: dividing the most-negative integer by -1
521      * returns the most-negative integer, and doesn't cause an exception.
522      *
523      * Pass in -1, -1L.
524      */
bigDivideOverflow(int idiv, long ldiv)525     static void bigDivideOverflow(int idiv, long ldiv) {
526         System.out.println("IntMath.bigDivideOverflow");
527         int mostNegInt = (int) 0x80000000;
528         long mostNegLong = (long) 0x8000000000000000L;
529 
530         int intDivResult = mostNegInt / idiv;
531         int intModResult = mostNegInt % idiv;
532         long longDivResult = mostNegLong / ldiv;
533         long longModResult = mostNegLong % ldiv;
534 
535         Main.assertTrue(intDivResult == mostNegInt);
536         Main.assertTrue(intModResult == 0);
537         Main.assertTrue(longDivResult == mostNegLong);
538         Main.assertTrue(longModResult == 0);
539     }
540 
541     /*
542      * Check "const" instructions.  We use negative values to ensure that
543      * sign-extension is happening.
544      */
checkConsts(byte small, short medium, int large, long huge)545     static void checkConsts(byte small, short medium, int large, long huge) {
546         System.out.println("IntMath.checkConsts");
547 
548         Main.assertTrue(small == 1);                     // const/4
549         Main.assertTrue(medium == -256);                 // const/16
550         Main.assertTrue(medium == -256L);                // const-wide/16
551         Main.assertTrue(large == -88888);                // const
552         Main.assertTrue(large == -88888L);               // const-wide/32
553         Main.assertTrue(huge == 0x9922334455667788L);    // const-wide
554     }
555 
556     /*
557      * Test some java.lang.Math functions.
558      *
559      * The method arguments are positive values.
560      */
jlmTests(int ii, long ll)561     static void jlmTests(int ii, long ll) {
562         System.out.println("IntMath.jlmTests");
563 
564         Main.assertTrue(Math.abs(ii) == ii);
565         Main.assertTrue(Math.abs(-ii) == ii);
566         Main.assertTrue(Math.min(ii, -5) == -5);
567         Main.assertTrue(Math.max(ii, -5) == ii);
568 
569         Main.assertTrue(Math.abs(ll) == ll);
570         Main.assertTrue(Math.abs(-ll) == ll);
571         Main.assertTrue(Math.min(ll, -5L) == -5L);
572         Main.assertTrue(Math.max(ll, -5L) == ll);
573     }
574 
run()575     public static void run() {
576         shiftTest1();
577         shiftTest2();
578         unsignedShiftTest();
579         shiftTest3(32);
580         convTest();
581         charSubTest();
582 
583         int[] intResults;
584         long[] longResults;
585 
586         intResults = intOperTest(70000, -3);
587         intOperCheck(intResults);
588         longResults = longOperTest(70000000000L, -3L);
589         longOperCheck(longResults);
590 
591         intResults = lit16Test(77777);
592         lit16Check(intResults);
593         intResults = lit8Test(-55555);
594         lit8Check(intResults);
595         divLiteralTest();
596 
597         intResults = intShiftTest(0xff00aa01, 8);
598         intShiftCheck(intResults);
599         longResults = longShiftTest(0xd5aa96deff00aa01L, 16);
600         long longRet = longShiftCheck(longResults);
601         Main.assertTrue(longRet == 0x96deff00aa010000L);
602 
603         Shorty shorts = truncateTest(-16717277);    // 0xff00ea23
604         truncateCheck(shorts);
605 
606         divideByZero(0);
607         bigDivideOverflow(-1, -1L);
608 
609         checkConsts((byte) 1, (short) -256, -88888, 0x9922334455667788L);
610 
611         unopCheck(unopTest(38));
612 
613         jlmTests(12345, 0x1122334455667788L);
614     }
615 }
616