Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     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 
     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 
    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 
    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      */
    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     }
    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      */
    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     }
    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      */
    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     }
    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      */
    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 
    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      */
    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     }
    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      */
    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     }
    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      */
    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     }
    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      */
    455     static int unopTest(int x) {
    456         x = -x;
    457         x ^= 0xffffffff;
    458         return x;
    459     }
    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      */
    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     }
    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      */
    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      */
    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      */
    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      */
    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 
    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