1// Copyright 2006 The Android Open Source Project
2
3/**
4 * Test arithmetic operations.
5 */
6public class IntMath {
7
8    static void shiftTest1() {
9        System.out.println("IntMath.shiftTest1");
10
11        final int[] mBytes = {
12            0x11, 0x22, 0x33, 0x44, 0x88, 0x99, 0xaa, 0xbb
13        };
14        long l;
15        int i1, i2;
16
17        i1 = mBytes[0] | mBytes[1] << 8 | mBytes[2] << 16 | mBytes[3] << 24;
18        i2 = mBytes[4] | mBytes[5] << 8 | mBytes[6] << 16 | mBytes[7] << 24;
19        l = i1 | ((long)i2 << 32);
20
21        assert(i1 == 0x44332211);
22        assert(i2 == 0xbbaa9988);
23        assert(l == 0xbbaa998844332211L);
24
25        l = (long)mBytes[0]
26            | (long)mBytes[1] << 8
27            | (long)mBytes[2] << 16
28            | (long)mBytes[3] << 24
29            | (long)mBytes[4] << 32
30            | (long)mBytes[5] << 40
31            | (long)mBytes[6] << 48
32            | (long)mBytes[7] << 56;
33
34        assert(l == 0xbbaa998844332211L);
35    }
36
37    static void shiftTest2() {
38        System.out.println("IntMath.shiftTest2");
39
40        long    a = 0x11;
41        long    b = 0x22;
42        long    c = 0x33;
43        long    d = 0x44;
44        long    e = 0x55;
45        long    f = 0x66;
46        long    g = 0x77;
47        long    h = 0x88;
48
49        long    result = ((a << 56) | (b << 48) | (c << 40) | (d << 32) |
50                         (e << 24) | (f << 16) | (g <<  8) | h);
51
52        assert(result == 0x1122334455667788L);
53    }
54
55    static void unsignedShiftTest() {
56        System.out.println("IntMath.unsignedShiftTest");
57
58        byte b = -4;
59        short s = -4;
60        char c = 0xfffc;
61        int i = -4;
62
63        b >>>= 4;
64        s >>>= 4;
65        c >>>= 4;
66        i >>>= 4;
67
68        assert((int) b == -1);
69        assert((int) s == -1);
70        assert((int) c == 0x0fff);
71        assert(i == 268435455);
72    }
73
74    static void convTest() {
75        System.out.println("IntMath.convTest");
76
77        float f;
78        double d;
79        int i;
80        long l;
81
82        /* int --> long */
83        i = 7654;
84        l = (long) i;
85        assert(l == 7654L);
86
87        i = -7654;
88        l = (long) i;
89        assert(l == -7654L);
90
91        /* long --> int (with truncation) */
92        l = 5678956789L;
93        i = (int) l;
94        assert(i == 1383989493);
95
96        l = -5678956789L;
97        i = (int) l;
98        assert(i == -1383989493);
99    }
100
101    static void charSubTest() {
102        System.out.println("IntMath.charSubTest");
103
104        char char1 = 0x00e9;
105        char char2 = 0xffff;
106        int i;
107
108        /* chars are unsigned-expanded to ints before subtraction */
109        i = char1 - char2;
110        assert(i == 0xffff00ea);
111    }
112
113    /*
114     * We pass in the arguments and return the results so the compiler
115     * doesn't do the math for us.  (x=70000, y=-3)
116     */
117    static int[] intOperTest(int x, int y) {
118        System.out.println("IntMath.intOperTest");
119
120        int[] results = new int[10];
121
122        /* this seems to generate "op-int" instructions */
123        results[0] = x + y;
124        results[1] = x - y;
125        results[2] = x * y;
126        results[3] = x * x;
127        results[4] = x / y;
128        results[5] = x % -y;
129        results[6] = x & y;
130        results[7] = x | y;
131        results[8] = x ^ y;
132
133        /* this seems to generate "op-int/2addr" instructions */
134        results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y);
135
136        return results;
137    }
138    static void intOperCheck(int[] results) {
139        System.out.println("IntMath.intOperCheck");
140
141        /* check this edge case while we're here (div-int/2addr) */
142        int minInt = -2147483648;
143        int negOne = -results[5];
144        int plusOne = 1;
145        int result = (((minInt + plusOne) - plusOne) / negOne) / negOne;
146        assert(result == minInt);
147
148        assert(results[0] == 69997);
149        assert(results[1] == 70003);
150        assert(results[2] == -210000);
151        assert(results[3] == 605032704);    // overflow / truncate
152        assert(results[4] == -23333);
153        assert(results[5] == 1);
154        assert(results[6] == 70000);
155        assert(results[7] == -3);
156        assert(results[8] == -70003);
157        assert(results[9] == 70000);
158    }
159
160    /*
161     * More operations, this time with 16-bit constants.  (x=77777)
162     */
163    static int[] lit16Test(int x) {
164        System.out.println("IntMath.lit16Test");
165
166        int[] results = new int[8];
167
168        /* try to generate op-int/lit16" instructions */
169        results[0] = x + 1000;
170        results[1] = 1000 - x;
171        results[2] = x * 1000;
172        results[3] = x / 1000;
173        results[4] = x % 1000;
174        results[5] = x & 1000;
175        results[6] = x | -1000;
176        results[7] = x ^ -1000;
177        return results;
178    }
179    static void lit16Check(int[] results) {
180        assert(results[0] == 78777);
181        assert(results[1] == -76777);
182        assert(results[2] == 77777000);
183        assert(results[3] == 77);
184        assert(results[4] == 777);
185        assert(results[5] == 960);
186        assert(results[6] == -39);
187        assert(results[7] == -76855);
188    }
189
190    /*
191     * More operations, this time with 8-bit constants.  (x=-55555)
192     */
193    static int[] lit8Test(int x) {
194        System.out.println("IntMath.lit8Test");
195
196        int[] results = new int[8];
197
198        /* try to generate op-int/lit8" instructions */
199        results[0] = x + 10;
200        results[1] = 10 - x;
201        results[2] = x * 10;
202        results[3] = x / 10;
203        results[4] = x % 10;
204        results[5] = x & 10;
205        results[6] = x | -10;
206        results[7] = x ^ -10;
207        return results;
208    }
209    static void lit8Check(int[] results) {
210        //for (int i = 0; i < results.length; i++)
211        //    System.out.println(" " + i + ": " + results[i]);
212
213        /* check this edge case while we're here (div-int/lit8) */
214        int minInt = -2147483648;
215        int result = minInt / -1;
216        assert(result == minInt);
217
218        assert(results[0] == -55545);
219        assert(results[1] == 55565);
220        assert(results[2] == -555550);
221        assert(results[3] == -5555);
222        assert(results[4] == -5);
223        assert(results[5] == 8);
224        assert(results[6] == -1);
225        assert(results[7] == 55563);
226    }
227
228
229    /*
230     * Shift some data.  (value=0xff00aa01, dist=8)
231     */
232    static int[] intShiftTest(int value, int dist) {
233        System.out.println("IntMath.intShiftTest");
234
235        int results[] = new int[4];
236
237        results[0] = value << dist;
238        results[1] = value >> dist;
239        results[2] = value >>> dist;
240
241        results[3] = (((value << dist) >> dist) >>> dist) << dist;
242        return results;
243    }
244    static void intShiftCheck(int[] results) {
245        System.out.println("IntMath.intShiftCheck");
246
247        assert(results[0] == 0x00aa0100);
248        assert(results[1] == 0xffff00aa);
249        assert(results[2] == 0x00ff00aa);
250        assert(results[3] == 0xaa00);
251    }
252
253    /*
254     * We pass in the arguments and return the results so the compiler
255     * doesn't do the math for us.  (x=70000000000, y=-3)
256     */
257    static long[] longOperTest(long x, long y) {
258        System.out.println("IntMath.longOperTest");
259
260        long[] results = new long[10];
261
262        /* this seems to generate "op-long" instructions */
263        results[0] = x + y;
264        results[1] = x - y;
265        results[2] = x * y;
266        results[3] = x * x;
267        results[4] = x / y;
268        results[5] = x % -y;
269        results[6] = x & y;
270        results[7] = x | y;
271        results[8] = x ^ y;
272
273        /* this seems to generate "op-long/2addr" instructions */
274        results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y);
275
276        return results;
277    }
278    static void longOperCheck(long[] results) {
279        System.out.println("IntMath.longOperCheck");
280
281        /* check this edge case while we're here (div-long/2addr) */
282        long minLong = -9223372036854775808L;
283        long negOne = -results[5];
284        long plusOne = 1;
285        long result = (((minLong + plusOne) - plusOne) / negOne) / negOne;
286        assert(result == minLong);
287
288        assert(results[0] == 69999999997L);
289        assert(results[1] == 70000000003L);
290        assert(results[2] == -210000000000L);
291        assert(results[3] == -6833923606740729856L);    // overflow
292        assert(results[4] == -23333333333L);
293        assert(results[5] == 1);
294        assert(results[6] == 70000000000L);
295        assert(results[7] == -3);
296        assert(results[8] == -70000000003L);
297        assert(results[9] == 70000000000L);
298
299        assert(results.length == 10);
300    }
301
302    /*
303     * Shift some data.  (value=0xd5aa96deff00aa01, dist=8)
304     */
305    static long[] longShiftTest(long value, int dist) {
306        System.out.println("IntMath.longShiftTest");
307
308        long results[] = new long[4];
309
310        results[0] = value << dist;
311        results[1] = value >> dist;
312        results[2] = value >>> dist;
313
314        results[3] = (((value << dist) >> dist) >>> dist) << dist;
315        return results;
316    }
317    static long longShiftCheck(long[] results) {
318        System.out.println("IntMath.longShiftCheck");
319
320        assert(results[0] == 0x96deff00aa010000L);
321        assert(results[1] == 0xffffd5aa96deff00L);
322        assert(results[2] == 0x0000d5aa96deff00L);
323        assert(results[3] == 0xffff96deff000000L);
324
325        assert(results.length == 4);
326
327        return results[0];      // test return-long
328    }
329
330
331    /*
332     * Try to cause some unary operations.
333     */
334    static int unopTest(int x) {
335        x = -x;
336        x ^= 0xffffffff;
337        return x;
338    }
339    static void unopCheck(int result) {
340        assert(result == 37);
341    }
342
343    static class Shorty {
344        public short mShort;
345        public char mChar;
346        public byte mByte;
347    };
348
349    /*
350     * Truncate an int.
351     */
352    static Shorty truncateTest(int x) {
353        System.out.println("IntMath.truncateTest");
354        Shorty shorts = new Shorty();
355
356        shorts.mShort = (short) x;
357        shorts.mChar = (char) x;
358        shorts.mByte = (byte) x;
359        return shorts;
360    }
361    static void truncateCheck(Shorty shorts) {
362        assert(shorts.mShort == -5597);     // 0xea23
363        assert(shorts.mChar == 59939);      // 0xea23
364        assert(shorts.mByte == 35);         // 0x23
365    }
366
367    /*
368     * Verify that we get a divide-by-zero exception.
369     */
370    static void divideByZero(int z) {
371        System.out.println("IntMath.divideByZero");
372
373        try {
374            int x = 100 / z;
375            assert(false);
376        } catch (ArithmeticException ae) {
377        }
378
379        try {
380            int x = 100 % z;
381            assert(false);
382        } catch (ArithmeticException ae) {
383        }
384
385        try {
386            long x = 100L / z;
387            assert(false);
388        } catch (ArithmeticException ae) {
389        }
390
391        try {
392            long x = 100L % z;
393            assert(false);
394        } catch (ArithmeticException ae) {
395        }
396    }
397
398    /*
399     * Check an edge condition: dividing the most-negative integer by -1
400     * returns the most-negative integer, and doesn't cause an exception.
401     *
402     * Pass in -1, -1L.
403     */
404    static void bigDivideOverflow(int idiv, long ldiv) {
405        System.out.println("IntMath.bigDivideOverflow");
406        int mostNegInt = (int) 0x80000000;
407        long mostNegLong = (long) 0x8000000000000000L;
408
409        int intDivResult = mostNegInt / idiv;
410        int intModResult = mostNegInt % idiv;
411        long longDivResult = mostNegLong / ldiv;
412        long longModResult = mostNegLong % ldiv;
413
414        assert(intDivResult == mostNegInt);
415        assert(intModResult == 0);
416        assert(longDivResult == mostNegLong);
417        assert(longModResult == 0);
418    }
419
420    /*
421     * Check "const" instructions.  We use negative values to ensure that
422     * sign-extension is happening.
423     */
424    static void checkConsts(byte small, short medium, int large, long huge) {
425        System.out.println("IntMath.checkConsts");
426
427        assert(small == 1);                     // const/4
428        assert(medium == -256);                 // const/16
429        assert(medium == -256L);                // const-wide/16
430        assert(large == -88888);                // const
431        assert(large == -88888L);               // const-wide/32
432        assert(huge == 0x9922334455667788L);    // const-wide
433    }
434
435    /*
436     * Test some java.lang.Math functions.
437     *
438     * The method arguments are positive values.
439     */
440    static void jlmTests(int ii, long ll) {
441        System.out.println("IntMath.jlmTests");
442
443        assert(Math.abs(ii) == ii);
444        assert(Math.abs(-ii) == ii);
445        assert(Math.min(ii, -5) == -5);
446        assert(Math.max(ii, -5) == ii);
447
448        assert(Math.abs(ll) == ll);
449        assert(Math.abs(-ll) == ll);
450        assert(Math.min(ll, -5L) == -5L);
451        assert(Math.max(ll, -5L) == ll);
452    }
453
454    public static void run() {
455        shiftTest1();
456        shiftTest2();
457        unsignedShiftTest();
458        convTest();
459        charSubTest();
460
461        int[] intResults;
462        long[] longResults;
463
464        intResults = intOperTest(70000, -3);
465        intOperCheck(intResults);
466        longResults = longOperTest(70000000000L, -3L);
467        longOperCheck(longResults);
468
469        intResults = lit16Test(77777);
470        lit16Check(intResults);
471        intResults = lit8Test(-55555);
472        lit8Check(intResults);
473
474        intResults = intShiftTest(0xff00aa01, 8);
475        intShiftCheck(intResults);
476        longResults = longShiftTest(0xd5aa96deff00aa01L, 16);
477        long longRet = longShiftCheck(longResults);
478        assert(longRet == 0x96deff00aa010000L);
479
480        Shorty shorts = truncateTest(-16717277);    // 0xff00ea23
481        truncateCheck(shorts);
482
483        divideByZero(0);
484        bigDivideOverflow(-1, -1L);
485
486        checkConsts((byte) 1, (short) -256, -88888, 0x9922334455667788L);
487
488        unopCheck(unopTest(38));
489
490        jlmTests(12345, 0x1122334455667788L);
491    }
492}
493