| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * Test arithmetic operations. |
| */ |
| public class IntMath { |
| |
| static void shiftTest1() { |
| System.out.println("IntMath.shiftTest1"); |
| |
| final int[] mBytes = { |
| 0x11, 0x22, 0x33, 0x44, 0x88, 0x99, 0xaa, 0xbb |
| }; |
| long l; |
| int i1, i2; |
| |
| i1 = mBytes[0] | mBytes[1] << 8 | mBytes[2] << 16 | mBytes[3] << 24; |
| i2 = mBytes[4] | mBytes[5] << 8 | mBytes[6] << 16 | mBytes[7] << 24; |
| l = i1 | ((long)i2 << 32); |
| |
| Main.assertTrue(i1 == 0x44332211); |
| Main.assertTrue(i2 == 0xbbaa9988); |
| Main.assertTrue(l == 0xbbaa998844332211L); |
| |
| l = (long)mBytes[0] |
| | (long)mBytes[1] << 8 |
| | (long)mBytes[2] << 16 |
| | (long)mBytes[3] << 24 |
| | (long)mBytes[4] << 32 |
| | (long)mBytes[5] << 40 |
| | (long)mBytes[6] << 48 |
| | (long)mBytes[7] << 56; |
| |
| Main.assertTrue(l == 0xbbaa998844332211L); |
| } |
| |
| static void shiftTest2() { |
| System.out.println("IntMath.shiftTest2"); |
| |
| long a = 0x11; |
| long b = 0x22; |
| long c = 0x33; |
| long d = 0x44; |
| long e = 0x55; |
| long f = 0x66; |
| long g = 0x77; |
| long h = 0x88; |
| |
| long result = ((a << 56) | (b << 48) | (c << 40) | (d << 32) | |
| (e << 24) | (f << 16) | (g << 8) | h); |
| |
| Main.assertTrue(result == 0x1122334455667788L); |
| } |
| |
| static void unsignedShiftTest() { |
| System.out.println("IntMath.unsignedShiftTest"); |
| |
| byte b = -4; |
| short s = -4; |
| char c = 0xfffc; |
| int i = -4; |
| |
| b >>>= 4; |
| s >>>= 4; |
| c >>>= 4; |
| i >>>= 4; |
| |
| Main.assertTrue((int) b == -1); |
| Main.assertTrue((int) s == -1); |
| Main.assertTrue((int) c == 0x0fff); |
| Main.assertTrue(i == 268435455); |
| } |
| |
| static void shiftTest3(int thirtyTwo) { |
| System.out.println("IntMath.shiftTest3"); |
| |
| int one = thirtyTwo / 32; |
| int sixteen = thirtyTwo / 2; |
| int thirtyThree = thirtyTwo + 1; |
| int sixtyFour = thirtyTwo * 2; |
| |
| Main.assertTrue(1 << thirtyTwo == 1); |
| Main.assertTrue((1 << sixteen) << sixteen == 0); |
| Main.assertTrue(1 << thirtyThree == 2); |
| Main.assertTrue(1 << -one == -2147483648); |
| Main.assertTrue(1 << -thirtyTwo == 1); |
| Main.assertTrue(1 << -thirtyThree == -2147483648); |
| Main.assertTrue(1 << thirtyThree == 2); |
| |
| Main.assertTrue(1 >> thirtyTwo == 1); |
| Main.assertTrue((1 >> sixteen) >> sixteen == 0); |
| Main.assertTrue(1 >> thirtyThree == 0); |
| Main.assertTrue(1 >> -one == 0); |
| Main.assertTrue(1 >> -thirtyTwo == 1); |
| Main.assertTrue(1 >> -thirtyThree == 0); |
| Main.assertTrue(-4 >> thirtyThree == -2); |
| |
| Main.assertTrue(1 >>> thirtyTwo == 1); |
| Main.assertTrue((1 >>> sixteen) >>> sixteen == 0); |
| Main.assertTrue(1 >>> thirtyThree == 0); |
| Main.assertTrue(1 >>> -one == 0); |
| Main.assertTrue(1 >>> -thirtyTwo == 1); |
| Main.assertTrue(1 >>> -thirtyThree == 0); |
| Main.assertTrue(-4 >>> thirtyThree == 2147483646); |
| } |
| |
| static void convTest() { |
| System.out.println("IntMath.convTest"); |
| |
| float f; |
| double d; |
| int i; |
| long l; |
| |
| /* int --> long */ |
| i = 7654; |
| l = (long) i; |
| Main.assertTrue(l == 7654L); |
| |
| i = -7654; |
| l = (long) i; |
| Main.assertTrue(l == -7654L); |
| |
| /* long --> int (with truncation) */ |
| l = 5678956789L; |
| i = (int) l; |
| Main.assertTrue(i == 1383989493); |
| |
| l = -5678956789L; |
| i = (int) l; |
| Main.assertTrue(i == -1383989493); |
| } |
| |
| static void charSubTest() { |
| System.out.println("IntMath.charSubTest"); |
| |
| char char1 = 0x00e9; |
| char char2 = 0xffff; |
| int i; |
| |
| /* chars are unsigned-expanded to ints before subtraction */ |
| i = char1 - char2; |
| Main.assertTrue(i == 0xffff00ea); |
| } |
| |
| /* |
| * We pass in the arguments and return the results so the compiler |
| * doesn't do the math for us. (x=70000, y=-3) |
| */ |
| static int[] intOperTest(int x, int y) { |
| System.out.println("IntMath.intOperTest"); |
| |
| int[] results = new int[10]; |
| |
| /* this seems to generate "op-int" instructions */ |
| results[0] = x + y; |
| results[1] = x - y; |
| results[2] = x * y; |
| results[3] = x * x; |
| results[4] = x / y; |
| results[5] = x % -y; |
| results[6] = x & y; |
| results[7] = x | y; |
| results[8] = x ^ y; |
| |
| /* this seems to generate "op-int/2addr" instructions */ |
| results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y); |
| |
| return results; |
| } |
| static void intOperCheck(int[] results) { |
| System.out.println("IntMath.intOperCheck"); |
| |
| /* check this edge case while we're here (div-int/2addr) */ |
| int minInt = -2147483648; |
| int negOne = -results[5]; |
| int plusOne = 1; |
| int result = (((minInt + plusOne) - plusOne) / negOne) / negOne; |
| Main.assertTrue(result == minInt); |
| |
| Main.assertTrue(results[0] == 69997); |
| Main.assertTrue(results[1] == 70003); |
| Main.assertTrue(results[2] == -210000); |
| Main.assertTrue(results[3] == 605032704); // overflow / truncate |
| Main.assertTrue(results[4] == -23333); |
| Main.assertTrue(results[5] == 1); |
| Main.assertTrue(results[6] == 70000); |
| Main.assertTrue(results[7] == -3); |
| Main.assertTrue(results[8] == -70003); |
| Main.assertTrue(results[9] == 70000); |
| } |
| |
| /* |
| * More operations, this time with 16-bit constants. (x=77777) |
| */ |
| static int[] lit16Test(int x) { |
| System.out.println("IntMath.lit16Test"); |
| |
| int[] results = new int[8]; |
| |
| /* try to generate op-int/lit16" instructions */ |
| results[0] = x + 1000; |
| results[1] = 1000 - x; |
| results[2] = x * 1000; |
| results[3] = x / 1000; |
| results[4] = x % 1000; |
| results[5] = x & 1000; |
| results[6] = x | -1000; |
| results[7] = x ^ -1000; |
| return results; |
| } |
| static void lit16Check(int[] results) { |
| Main.assertTrue(results[0] == 78777); |
| Main.assertTrue(results[1] == -76777); |
| Main.assertTrue(results[2] == 77777000); |
| Main.assertTrue(results[3] == 77); |
| Main.assertTrue(results[4] == 777); |
| Main.assertTrue(results[5] == 960); |
| Main.assertTrue(results[6] == -39); |
| Main.assertTrue(results[7] == -76855); |
| } |
| |
| /* |
| * More operations, this time with 8-bit constants. (x=-55555) |
| */ |
| static int[] lit8Test(int x) { |
| System.out.println("IntMath.lit8Test"); |
| |
| int[] results = new int[8]; |
| |
| /* try to generate op-int/lit8" instructions */ |
| results[0] = x + 10; |
| results[1] = 10 - x; |
| results[2] = x * 10; |
| results[3] = x / 10; |
| results[4] = x % 10; |
| results[5] = x & 10; |
| results[6] = x | -10; |
| results[7] = x ^ -10; |
| return results; |
| } |
| static void lit8Check(int[] results) { |
| //for (int i = 0; i < results.length; i++) |
| // System.out.println(" " + i + ": " + results[i]); |
| |
| /* check this edge case while we're here (div-int/lit8) */ |
| int minInt = -2147483648; |
| int result = minInt / -1; |
| Main.assertTrue(result == minInt); |
| |
| Main.assertTrue(results[0] == -55545); |
| Main.assertTrue(results[1] == 55565); |
| Main.assertTrue(results[2] == -555550); |
| Main.assertTrue(results[3] == -5555); |
| Main.assertTrue(results[4] == -5); |
| Main.assertTrue(results[5] == 8); |
| Main.assertTrue(results[6] == -1); |
| Main.assertTrue(results[7] == 55563); |
| } |
| |
| /* |
| * Make sure special-cased literal division matches |
| * normal division. |
| */ |
| static void divLiteralTestBody(int start, int count) { |
| int normal = 0; |
| int special = 0; |
| for (int i = 0; i < count; i++) { |
| for (int j = 3; j < 16; j++) { |
| switch(j) { |
| case 3: |
| normal = (start+i) / j; |
| special = (start+i) / 3; |
| break; |
| case 4: |
| normal = (start+i) / j; |
| special = (start+i) / 4; |
| break; |
| case 5: |
| normal = (start+i) / j; |
| special = (start+i) / 5; |
| break; |
| case 6: |
| normal = (start+i) / j; |
| special = (start+i) / 6; |
| break; |
| case 7: |
| normal = (start+i) / j; |
| special = (start+i) / 7; |
| break; |
| case 8: |
| normal = (start+i) / j; |
| special = (start+i) / 8; |
| break; |
| case 9: |
| normal = (start+i) / j; |
| special = (start+i) / 9; |
| break; |
| case 10: |
| normal = (start+i) / j; |
| special = (start+i) / 10; |
| break; |
| case 11: |
| normal = (start+i) / j; |
| special = (start+i) / 11; |
| break; |
| case 12: |
| normal = (start+i) / j; |
| special = (start+i) / 12; |
| break; |
| case 13: |
| normal = (start+i) / j; |
| special = (start+i) / 13; |
| break; |
| case 14: |
| normal = (start+i) / j; |
| special = (start+i) / 14; |
| break; |
| case 15: |
| normal = (start+i) / j; |
| special = (start+i) / 15; |
| break; |
| } |
| Main.assertTrue(normal == special); |
| } |
| } |
| } |
| |
| static void divLiteralTest() { |
| System.out.println("IntMath.divLiteralTest"); |
| divLiteralTestBody(-1000, 2000); |
| divLiteralTestBody(0x7fffffff-2000, 2000); |
| divLiteralTestBody(0xfff0ffff, 2000); |
| } |
| |
| /* |
| * Shift some data. (value=0xff00aa01, dist=8) |
| */ |
| static int[] intShiftTest(int value, int dist) { |
| System.out.println("IntMath.intShiftTest"); |
| |
| int results[] = new int[4]; |
| |
| results[0] = value << dist; |
| results[1] = value >> dist; |
| results[2] = value >>> dist; |
| |
| results[3] = (((value << dist) >> dist) >>> dist) << dist; |
| return results; |
| } |
| static void intShiftCheck(int[] results) { |
| System.out.println("IntMath.intShiftCheck"); |
| |
| Main.assertTrue(results[0] == 0x00aa0100); |
| Main.assertTrue(results[1] == 0xffff00aa); |
| Main.assertTrue(results[2] == 0x00ff00aa); |
| Main.assertTrue(results[3] == 0xaa00); |
| } |
| |
| /* |
| * We pass in the arguments and return the results so the compiler |
| * doesn't do the math for us. (x=70000000000, y=-3) |
| */ |
| static long[] longOperTest(long x, long y) { |
| System.out.println("IntMath.longOperTest"); |
| |
| long[] results = new long[10]; |
| |
| /* this seems to generate "op-long" instructions */ |
| results[0] = x + y; |
| results[1] = x - y; |
| results[2] = x * y; |
| results[3] = x * x; |
| results[4] = x / y; |
| results[5] = x % -y; |
| results[6] = x & y; |
| results[7] = x | y; |
| results[8] = x ^ y; |
| |
| /* this seems to generate "op-long/2addr" instructions */ |
| results[9] = x + ((((((((x + y) - y) * y) / y) % y) & y) | y) ^ y); |
| |
| return results; |
| } |
| static void longOperCheck(long[] results) { |
| System.out.println("IntMath.longOperCheck"); |
| |
| /* check this edge case while we're here (div-long/2addr) */ |
| long minLong = -9223372036854775808L; |
| long negOne = -results[5]; |
| long plusOne = 1; |
| long result = (((minLong + plusOne) - plusOne) / negOne) / negOne; |
| Main.assertTrue(result == minLong); |
| |
| Main.assertTrue(results[0] == 69999999997L); |
| Main.assertTrue(results[1] == 70000000003L); |
| Main.assertTrue(results[2] == -210000000000L); |
| Main.assertTrue(results[3] == -6833923606740729856L); // overflow |
| Main.assertTrue(results[4] == -23333333333L); |
| Main.assertTrue(results[5] == 1); |
| Main.assertTrue(results[6] == 70000000000L); |
| Main.assertTrue(results[7] == -3); |
| Main.assertTrue(results[8] == -70000000003L); |
| Main.assertTrue(results[9] == 70000000000L); |
| |
| Main.assertTrue(results.length == 10); |
| } |
| |
| /* |
| * Shift some data. (value=0xd5aa96deff00aa01, dist=8) |
| */ |
| static long[] longShiftTest(long value, int dist) { |
| System.out.println("IntMath.longShiftTest"); |
| |
| long results[] = new long[4]; |
| |
| results[0] = value << dist; |
| results[1] = value >> dist; |
| results[2] = value >>> dist; |
| |
| results[3] = (((value << dist) >> dist) >>> dist) << dist; |
| return results; |
| } |
| static long longShiftCheck(long[] results) { |
| System.out.println("IntMath.longShiftCheck"); |
| |
| Main.assertTrue(results[0] == 0x96deff00aa010000L); |
| Main.assertTrue(results[1] == 0xffffd5aa96deff00L); |
| Main.assertTrue(results[2] == 0x0000d5aa96deff00L); |
| Main.assertTrue(results[3] == 0xffff96deff000000L); |
| |
| Main.assertTrue(results.length == 4); |
| |
| return results[0]; // test return-long |
| } |
| |
| |
| /* |
| * Try to cause some unary operations. |
| */ |
| static int unopTest(int x) { |
| x = -x; |
| x ^= 0xffffffff; |
| return x; |
| } |
| static void unopCheck(int result) { |
| Main.assertTrue(result == 37); |
| } |
| |
| static class Shorty { |
| public short mShort; |
| public char mChar; |
| public byte mByte; |
| }; |
| |
| /* |
| * Truncate an int. |
| */ |
| static Shorty truncateTest(int x) { |
| System.out.println("IntMath.truncateTest"); |
| Shorty shorts = new Shorty(); |
| |
| shorts.mShort = (short) x; |
| shorts.mChar = (char) x; |
| shorts.mByte = (byte) x; |
| return shorts; |
| } |
| static void truncateCheck(Shorty shorts) { |
| Main.assertTrue(shorts.mShort == -5597); // 0xea23 |
| Main.assertTrue(shorts.mChar == 59939); // 0xea23 |
| Main.assertTrue(shorts.mByte == 35); // 0x23 |
| } |
| |
| /* |
| * Verify that we get a divide-by-zero exception. |
| */ |
| static void divideByZero(int z) { |
| System.out.println("IntMath.divideByZero"); |
| |
| try { |
| int x = 100 / z; |
| Main.assertTrue(false); |
| } catch (ArithmeticException ae) { |
| } |
| |
| try { |
| int x = 100 % z; |
| Main.assertTrue(false); |
| } catch (ArithmeticException ae) { |
| } |
| |
| try { |
| long x = 100L / z; |
| Main.assertTrue(false); |
| } catch (ArithmeticException ae) { |
| } |
| |
| try { |
| long x = 100L % z; |
| Main.assertTrue(false); |
| } catch (ArithmeticException ae) { |
| } |
| } |
| |
| /* |
| * Check an edge condition: dividing the most-negative integer by -1 |
| * returns the most-negative integer, and doesn't cause an exception. |
| * |
| * Pass in -1, -1L. |
| */ |
| static void bigDivideOverflow(int idiv, long ldiv) { |
| System.out.println("IntMath.bigDivideOverflow"); |
| int mostNegInt = (int) 0x80000000; |
| long mostNegLong = (long) 0x8000000000000000L; |
| |
| int intDivResult = mostNegInt / idiv; |
| int intModResult = mostNegInt % idiv; |
| long longDivResult = mostNegLong / ldiv; |
| long longModResult = mostNegLong % ldiv; |
| |
| Main.assertTrue(intDivResult == mostNegInt); |
| Main.assertTrue(intModResult == 0); |
| Main.assertTrue(longDivResult == mostNegLong); |
| Main.assertTrue(longModResult == 0); |
| } |
| |
| /* |
| * Check "const" instructions. We use negative values to ensure that |
| * sign-extension is happening. |
| */ |
| static void checkConsts(byte small, short medium, int large, long huge) { |
| System.out.println("IntMath.checkConsts"); |
| |
| Main.assertTrue(small == 1); // const/4 |
| Main.assertTrue(medium == -256); // const/16 |
| Main.assertTrue(medium == -256L); // const-wide/16 |
| Main.assertTrue(large == -88888); // const |
| Main.assertTrue(large == -88888L); // const-wide/32 |
| Main.assertTrue(huge == 0x9922334455667788L); // const-wide |
| } |
| |
| /* |
| * Test some java.lang.Math functions. |
| * |
| * The method arguments are positive values. |
| */ |
| static void jlmTests(int ii, long ll) { |
| System.out.println("IntMath.jlmTests"); |
| |
| Main.assertTrue(Math.abs(ii) == ii); |
| Main.assertTrue(Math.abs(-ii) == ii); |
| Main.assertTrue(Math.min(ii, -5) == -5); |
| Main.assertTrue(Math.max(ii, -5) == ii); |
| |
| Main.assertTrue(Math.abs(ll) == ll); |
| Main.assertTrue(Math.abs(-ll) == ll); |
| Main.assertTrue(Math.min(ll, -5L) == -5L); |
| Main.assertTrue(Math.max(ll, -5L) == ll); |
| } |
| |
| public static void run() { |
| shiftTest1(); |
| shiftTest2(); |
| unsignedShiftTest(); |
| shiftTest3(32); |
| convTest(); |
| charSubTest(); |
| |
| int[] intResults; |
| long[] longResults; |
| |
| intResults = intOperTest(70000, -3); |
| intOperCheck(intResults); |
| longResults = longOperTest(70000000000L, -3L); |
| longOperCheck(longResults); |
| |
| intResults = lit16Test(77777); |
| lit16Check(intResults); |
| intResults = lit8Test(-55555); |
| lit8Check(intResults); |
| divLiteralTest(); |
| |
| intResults = intShiftTest(0xff00aa01, 8); |
| intShiftCheck(intResults); |
| longResults = longShiftTest(0xd5aa96deff00aa01L, 16); |
| long longRet = longShiftCheck(longResults); |
| Main.assertTrue(longRet == 0x96deff00aa010000L); |
| |
| Shorty shorts = truncateTest(-16717277); // 0xff00ea23 |
| truncateCheck(shorts); |
| |
| divideByZero(0); |
| bigDivideOverflow(-1, -1L); |
| |
| checkConsts((byte) 1, (short) -256, -88888, 0x9922334455667788L); |
| |
| unopCheck(unopTest(38)); |
| |
| jlmTests(12345, 0x1122334455667788L); |
| } |
| } |