/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package jikesRVM.core.bytecode;
import org.junit.Test;
import gov.nasa.jpf.annotation.Conditional;
import gov.nasa.jpf.util.test.TestJPF;
public class TestArithmetic extends TestJPF {
private static int int_3 = -3;
private static int int1 = 1;
private static int int3 = 3;
private static int int5 = 5;
private static int int33 = 33;
private static int int65 = 65;
private static long long_3 = -3;
private static long long_1 = -1;
private static long long0 = 0;
private static long long2 = 2;
private static long long10000000000 = 10000000000L;
private static long long0x0110000000000011 = 0x0110000000000011L;
private static long long0x1010000000000101 = 0x1010000000000101L;
private static long long0xBEEFBEEFCAFEBABE = 0xBEEFBEEFCAFEBABEL;
static String[] JPF_CONFIGURATION = new String[]{"+stack=HybridStackHandler", "+nhandler.delegateUnhandledNative", "+search.class=.search.RandomSearch", "+choice=MapChoice"};
@Conditional
static boolean a = true;
@Test
public void test() {
if (verifyNoPropertyViolation(JPF_CONFIGURATION)) {
if (a) {
System.out.println();
System.out.println("-- itest --");
itest();
System.out.println();
System.out.println("-- ltest --");
ltest();
System.out.println();
System.out.println("-- ftest --");
ftest();
System.out.println();
System.out.println("-- dtest --");
dtest();
System.out.println();
System.out.println("-- nanTestFloat --");
nanTestFloat();
System.out.println();
System.out.println("-- nanTestDouble --");
nanTestDouble();
System.out.println();
System.out.println("-- remTest --");
remTest();
}
}
}
private static void itest() {
int a = int3;
assertEquals(4, a + 1);// iadd
assertEquals(2, a - 1);// isub
assertEquals(9, a * 3);// imul
assertEquals(1, a / 2);// idiv
assertEquals(1, a % 2);// irem
assertEquals(-3, -a);// ineg
assertEquals(4, ++a);// iinc
a = int_3;
assertEquals(-2, a + 1);// iadd
assertEquals(-4, a - 1);// isub
assertEquals(-9, a * 3);// imul
assertEquals(-1, a / 2);// idiv
assertEquals(-1, a % 2);// irem
assertEquals(3, -a);// ineg
assertEquals(-2, ++a); // iinc
a = int3; // 0x00000011j
int b = int5; // 0x00000101
assertEquals(1, a & b);// iand
assertEquals(7, a | b);// ior
assertEquals(6, a ^ b);// ixor
a = int_3; // 0xfffffffd;
assertEquals(-6, a << 1);// ishl
assertEquals(-2, a >> 1);// ishr
assertEquals(2147483646, a >>> 1);// iushr
// funny Java shift cases
a = int1;
assertEquals(1, a << 32);
assertEquals(0, (a << 16) << 16);
assertEquals(2, a << 33);
assertEquals(-2147483648, a << -1);
assertEquals(1, a << -32);
assertEquals(-2147483648, a << -33);
assertEquals(2, 1 << int33);
assertEquals(1, a >> 32);
assertEquals(0, (a >> 16) >> 16);
assertEquals(0, a >> 33);
assertEquals(0, a >> -1);
assertEquals(1, a >> -32);
assertEquals(0, a >> -33);
assertEquals(-2, -4 >> int33);
assertEquals(1, a >>> 32);
assertEquals(0, (a >>> 16) >>> 16);
assertEquals(0, a >>> 33);
assertEquals(0, a >>> -1);
assertEquals(1, a >>> -32);
assertEquals(0, a >>> -33);
assertEquals(2147483646, -4 >>> int33);
// IA32 bit test patterns
assertEquals(true, ((1 << int1) & int3) != 0);
assertEquals(false, ((1 << int1) & int3) == 0);
assertEquals(true, ((1 << int33) & int3) != 0);
assertEquals(true, (int3 & (1 << int1)) != 0);
assertEquals(false, (int3 & (1 << int1)) == 0);
assertEquals(true, (int3 & (1 << int33)) != 0);
if (((1 << int1) & int3) != 0) {
System.out.println("taken");
} else {
fail();
}
assertEquals(true, ((int3 >> int1) & 1) == 1);
assertEquals(false, ((int3 >> int1) & 1) != 1);
assertEquals(true, ((int3 >> int1) & 1) != 0);
assertEquals(false, ((int3 >> int1) & 1) == 0);
assertEquals(true, ((int3 >> int33) & 1) == 1);
if (((int3 >> int1) & 1) != 0) {
System.out.println("taken");
} else {
fail();
}
assertEquals(true, ((int3 >>> int1) & 1) == 1);
assertEquals(false, ((int3 >>> int1) & 1) != 1);
assertEquals(true, ((int3 >>> int1) & 1) != 0);
assertEquals(false, ((int3 >>> int1) & 1) == 0);
assertEquals(true, ((int3 >>> int33) & 1) == 1);
if (((int3 >>> int1) & 1) == 1) {
System.out.println("taken");
} else {
fail();
}
// Rotate tests
assertEquals(10, (int5 << 1)|(int5 >>> -1)); // Rotate left by 1
assertEquals(10, (int5 >>> -1)|(int5 << 1));// Rotate left by 1
assertEquals(-2147483646 , (int5 << -1)|(int5 >>> 1));// Rotate right by 1
assertEquals(-2147483646 , (int5 >>> 1)|(int5 << -1));// Rotate right by 1
assertEquals(10, (int5 << int1)|(int5 >>> -int1));// Rotate left by 1
assertEquals(10, (int5 >>> -int1)|(int5 << int1));// Rotate left by 1
assertEquals(-2147483646, (int5 << -int1)|(int5 >>> int1));// Rotate right by 1
assertEquals(-2147483646, (int5 >>> int1)|(int5 << -int1));// Rotate right by 1
}
private static void ltest() {
long a = long10000000000;
long b = long2;
assertEquals(10000000002l ,a + b); // ladd
assertEquals(9999999998l ,a - b); // lsub
assertEquals(20000000000l ,a * b); // lmul
assertEquals(5000000000l ,a / b); // ldiv
assertEquals(0l ,a % b); // lrem
assertEquals(-2l ,-b); // lneg
assertEquals(-10000000000l ,-a); // lneg
a = long_3;
assertEquals(-1l ,a + 2); // ladd
assertEquals(-5l ,a - 2); // lsub
assertEquals(-9l ,a * 3); // lmul
assertEquals(-1l ,a / 2); // ldiv
assertEquals(-1l ,a % 2); // lrem
assertEquals(3l ,-a); // lneg
a = long0x0110000000000011;
b = long0x1010000000000101;
assertEquals(4503599627370497l ,a & b); // land
assertEquals(1229482698272145681l ,a | b); // lor
assertEquals(1224979098644775184l ,a ^ b); // lxor
// bit patterns that can be optimized for certain operators if converting
// long operators into int operators
long long0x00000000FFFFFFFF = 0x00000000FFFFFFFFL;
long long0xFFFFFFFF00000000 = 0xFFFFFFFF00000000L;
long long0x00000001FFFFFFFF = 0x00000001FFFFFFFFL;
long long0xFFFFFFFF00000001 = 0xFFFFFFFF00000001L;
long long0x0000000100000000 = 0x0000000100000000L;
long long0x0000000100000001 = 0x0000000100000001L;
a = long_1;
assertEquals(-4294967295l ,a * long0x00000000FFFFFFFF);
assertEquals(4294967296l ,a * long0xFFFFFFFF00000000);
assertEquals(-8589934591l ,a * long0x00000001FFFFFFFF);
assertEquals(4294967295l ,a * long0xFFFFFFFF00000001);
assertEquals(-4294967296l ,a * long0x0000000100000000);
assertEquals(-4294967297l ,a * long0x0000000100000001);
assertEquals(4294967295l ,a & long0x00000000FFFFFFFF);
assertEquals(-4294967296l ,a & long0xFFFFFFFF00000000);
assertEquals(8589934591l ,a & long0x00000001FFFFFFFF);
assertEquals(-4294967295l ,a & long0xFFFFFFFF00000001);
assertEquals(4294967296l ,a & long0x0000000100000000);
assertEquals(4294967297l ,a & long0x0000000100000001);
a = long0;
assertEquals(4294967295l ,a | long0x00000000FFFFFFFF);
assertEquals(-4294967296l ,a | long0xFFFFFFFF00000000);
assertEquals(8589934591l ,a | long0x00000001FFFFFFFF);
assertEquals(-4294967295l ,a | long0xFFFFFFFF00000001);
assertEquals(4294967297l ,a | long0x0000000100000001);
assertEquals(4294967295l ,a ^ long0x00000000FFFFFFFF);
assertEquals(-4294967296l ,a ^ long0xFFFFFFFF00000000);
assertEquals(8589934591l ,a ^ long0x00000001FFFFFFFF);
assertEquals(-4294967295l ,a ^ long0xFFFFFFFF00000001);
assertEquals(4294967297l ,a ^ long0x0000000100000001);
a = long0xBEEFBEEFCAFEBABE;
assertEquals(9070106573795063164l ,a << 1); // lshl
assertEquals(-306530926119425288l ,a << 2);
assertEquals(-613061852238850576l ,a << 3);
assertEquals(-1226123704477701152l ,a << 4);
assertEquals(-1171235197933666816l ,a << 8);
assertEquals(-4688305491665879040l ,a << 16);
assertEquals(-3819410108757049344l ,a << 32);
assertEquals(-7638820217514098688l ,a << 33);
assertEquals(3169103638681354240l ,a << 34);
assertEquals(6338207277362708480l ,a << 35);
assertEquals(-5770329518984134656l ,a << 36);
assertEquals(-91551935198396416l ,a << 40);
assertEquals(-4990551337079930880l ,a << 48);
assertEquals(-4755801206503243776l ,a << 56);
assertEquals(0l ,a << 63);
assertEquals(-4688318749957244226l ,a << 64);
assertEquals(9070106573795063164l ,a << 65);
assertEquals(9070106573795063164l ,a << int65);
assertEquals(-2344159374978622113l ,a >> 1); // lshr
assertEquals(-1172079687489311057l ,a >> 2);
assertEquals(-586039843744655529l ,a >> 3);
assertEquals(-293019921872327765l ,a >> 4);
assertEquals(-18313745117020486l ,a >> 8);
assertEquals(-71538066863362l ,a >> 16);
assertEquals(-1091584273l ,a >> 32);
assertEquals(-545792137l ,a >> 33);
assertEquals(-272896069l ,a >> 34);
assertEquals(-136448035l ,a >> 35);
assertEquals(-68224018l ,a >> 36);
assertEquals(-4264002l ,a >> 40);
assertEquals(-16657l ,a >> 48);
assertEquals(-66l ,a >> 56);
assertEquals(-1l ,a >> 63);
assertEquals(-4688318749957244226l ,a >> 64);
assertEquals(-2344159374978622113l ,a >> 65);
assertEquals(-2344159374978622113l ,a >> int65);
assertEquals(6879212661876153695l ,a >>> 1); // lushr
assertEquals(3439606330938076847l ,a >>> 2);
assertEquals(1719803165469038423l ,a >>> 3);
assertEquals(859901582734519211l ,a >>> 4);
assertEquals(53743848920907450l ,a >>> 8);
assertEquals(209936909847294l ,a >>> 16);
assertEquals(3203383023l ,a >>> 32);
assertEquals(1601691511l ,a >>> 33);
assertEquals(800845755l ,a >>> 34);
assertEquals(400422877l ,a >>> 35);
assertEquals(200211438l ,a >>> 36);
assertEquals(12513214l ,a >>> 40);
assertEquals(48879l ,a >>> 48);
assertEquals(190l ,a >>> 56);
assertEquals(1l ,a >>> 63);
assertEquals(-4688318749957244226l ,a >>> 64);
assertEquals(6879212661876153695l ,a >>> 65);
assertEquals(6879212661876153695l ,a >>> int65);
}
private static float float0 = 0.0f;
private static float float0_9 = 0.9f;
private static float float1 = 1.0f;
private static float float1_5 = 1.5f;
private static float float2 = 2.0f;
private static float float_maxint = (float)Integer.MAX_VALUE;
private static float float_minint = (float)Integer.MIN_VALUE;
private static double double0 = 0.0f;
private static double double1 = 1.0f;
private static double double2 = 2.0f;
private static double double_maxint = (double)Integer.MAX_VALUE;
private static double double_minint = (double)Integer.MIN_VALUE;
private static float float_maxlong = (float)Long.MAX_VALUE;
private static float float_minlong = (float)Long.MIN_VALUE;
private static double double_maxlong = (double)Long.MAX_VALUE;
private static double double_minlong = (double)Long.MIN_VALUE;
private static void ftest() {
// f2i, d2i, f2l and d2l tests
assertEquals(0f ,(int)float0);
assertEquals(1f ,(int)float1);
assertEquals(0f ,(int)double0);
assertEquals(1f ,(int)double1);
assertEquals(0f ,(int)Float.NaN);
assertEquals(0f ,(int)-Float.NaN);
assertEquals(0f ,(int)Double.NaN);
assertEquals(0f ,(int)-Double.NaN);
float positiveInfinity = Float.POSITIVE_INFINITY;
assertEquals(2147483647f ,(int)positiveInfinity);
assertEquals(-2147483648f ,(int)Float.NEGATIVE_INFINITY);
assertEquals(2147483647f ,(int)float_maxint);
assertEquals(-2147483648f ,(int)float_minint);
assertEquals(2147483647f ,(int)double_maxint);
assertEquals(-2147483648f ,(int)double_minint);
assertEquals(0f ,(long)float0);
assertEquals(1f ,(long)float1);
assertEquals(0f ,(long)double0);
assertEquals(1f ,(long)double1);
assertEquals(0f ,(long)Float.NaN);
assertEquals(0f ,(long)-Float.NaN);
assertEquals(0f ,(long)Double.NaN);
assertEquals(0f ,(long)-Double.NaN);
assertEquals(9223372036854775807f ,(long)positiveInfinity);
assertEquals(-9223372036854775808f ,(long)Float.NEGATIVE_INFINITY);
assertEquals(9223372036854775807f ,(long)float_maxlong);
assertEquals(-9223372036854775808f ,(long)float_minlong);
assertEquals(9223372036854775807f ,(long)double_maxlong);
assertEquals(-9223372036854775808f ,(long)double_minlong);
float a = float1;
float b = float2;
assertEquals(Integer.toHexString(Float.floatToIntBits(3.0F)) ,Integer.toHexString(Float.floatToIntBits(a + b))); // fadd
assertEquals(Integer.toHexString(Float.floatToIntBits(-1.0F)) ,Integer.toHexString(Float.floatToIntBits(a - b))); // fsub
assertEquals(Integer.toHexString(Float.floatToIntBits(2.0F)) ,Integer.toHexString(Float.floatToIntBits(a * b))); // fmul
assertEquals(Integer.toHexString(Float.floatToIntBits(0.5F)) ,Integer.toHexString(Float.floatToIntBits(a / b))); // fdiv
assertEquals(Integer.toHexString(Float.floatToIntBits(-1.0F)) ,Integer.toHexString(Float.floatToIntBits(-a))); // fneg
a = float1_5;
b = float0_9;
assertEquals(Integer.toHexString(Float.floatToIntBits(0.6F)) ,Integer.toHexString(Float.floatToIntBits(a % b))); // frem
assertTrue(Float.isNaN(Float.NaN));
assertTrue(Float.isNaN(float0/float0));
assertTrue(Float.isNaN(Float.NaN + Float.NaN));
assertTrue(Float.isNaN(Float.NaN + float2));
assertTrue(Float.isNaN(Float.NaN * float2));
assertTrue(Float.isNaN((float0 / 0.0f) * positiveInfinity));
assertTrue(Float.isNaN((float1 / 0.0f) * 0.0f));
assertTrue(Float.isNaN((float1 / 0.0f) - (float1 / 0.0f)));
assertTrue(Float.isNaN((float1 / 0.0f) / (float1 / 0.0f)));
assertTrue(Float.isNaN((-float1 / 0.0f) * 0.0f));
assertTrue(Float.isNaN((-float1 / 0.0f) - (-float1 / 0.0f)));
assertFalse(Float.NaN > float1);
assertFalse(Float.NaN < float1);
assertFalse(Float.NaN == float1);
assertFalse(Float.NaN == -float1);
assertFalse(Float.NaN > positiveInfinity);
assertFalse(Float.NaN < positiveInfinity);
assertTrue(positiveInfinity == positiveInfinity);
assertTrue((-positiveInfinity == Float.NEGATIVE_INFINITY));
assertTrue(Float.NEGATIVE_INFINITY < float1);
assertTrue((-float1/0.0) == (-float1/0.0));
assertEquals(positiveInfinity,float1/0.0);
assertEquals(positiveInfinity ,(float1/0.0) + 2.0);
assertEquals(positiveInfinity ,(float1/0.0) * 0.5);
assertEquals(positiveInfinity ,(float1/0.0) + (float1/0.0));
assertEquals(positiveInfinity ,(float1/0.0) * (float1/0.0));
assertEquals(positiveInfinity ,Math.abs(-float1/0.0));
assertEquals(Float.NEGATIVE_INFINITY ,-float1/0.0);
assertEquals(Float.NEGATIVE_INFINITY ,(-float1/0.0) + 2.0);
assertEquals(Float.NEGATIVE_INFINITY ,(-float1/0.0) * 0.5);
assertEquals(2147483647f ,(int)(float1/0.0));
assertEquals(-2147483648f ,(int)(-float1/0.0));
assertEquals(0f ,(int)Float.NaN);
}
private static void dtest() {
double a = 1;
double b = 2;
assertEquals(Long.toHexString(Double.doubleToLongBits(3.0D)), Long.toHexString(Double.doubleToLongBits(a + b))); // dadd
assertEquals(Long.toHexString(Double.doubleToLongBits(-1.0D)),Long.toHexString(Double.doubleToLongBits(a - b))); // dsub
assertEquals(Long.toHexString(Double.doubleToLongBits(2.0D)),Long.toHexString(Double.doubleToLongBits(a * b))); // dmul
assertEquals(Long.toHexString(Double.doubleToLongBits(0.5D)),Long.toHexString(Double.doubleToLongBits(a / b))); // ddiv
assertEquals(Long.toHexString(Double.doubleToLongBits(-1.0D)),Long.toHexString(Double.doubleToLongBits(-a))); // dneg
a = 1.5;
b = 0.9;
assertEquals(Long.toHexString(Double.doubleToLongBits(0.6D)),Long.toHexString(Double.doubleToLongBits(a % b))); // drem
assertTrue(Double.isNaN(double0/double0));
assertTrue(Double.isNaN(Double.NaN + Double.NaN));
assertTrue(Double.isNaN(Double.NaN + double2));
assertTrue(Double.isNaN(Double.NaN * double2));
double positiveInfinity = Double.POSITIVE_INFINITY;
assertTrue(Double.isNaN((double0 / 0.0) * positiveInfinity));
assertTrue(Double.isNaN((double1 / 0.0) * 0.0));
assertTrue(Double.isNaN((double1 / 0.0) - (double1 / 0.0)));
assertTrue(Double.isNaN((double1 / 0.0) / (double1 / 0.0)));
assertTrue(Double.isNaN((-double1 / 0.0) * 0.0));
assertTrue(Double.isNaN((-double1 / 0.0) - (-double1 / 0.0)));
assertFalse(Double.NaN > double1);
assertFalse(Double.NaN < double1);
assertFalse(Double.NaN == double1);
assertFalse(Double.NaN == -double1);
assertFalse(Double.NaN > positiveInfinity);
assertFalse(Double.NaN < positiveInfinity);
assertTrue(positiveInfinity == positiveInfinity);
assertTrue(-positiveInfinity == Double.NEGATIVE_INFINITY);
assertTrue(Double.NEGATIVE_INFINITY < double1);
assertTrue((-double1/0.0) == (-double1/0.0));
assertEquals(positiveInfinity ,double1/0.0);
assertEquals(positiveInfinity,(double1/0.0) + 2.0);
assertEquals(positiveInfinity,(double1/0.0) * 0.5);
assertEquals(positiveInfinity,(double1/0.0) + (double1/0.0));
assertEquals(positiveInfinity,(double1/0.0) * (double1/0.0));
assertEquals(positiveInfinity,Math.abs(-double1/0.0));
assertEquals(Double.NEGATIVE_INFINITY ,-double1/0.0);
assertEquals(Double.NEGATIVE_INFINITY,(-double1/0.0) + 2.0);
assertEquals(Double.NEGATIVE_INFINITY,(-double1/0.0) * 0.5);
assertEquals(2147483647 ,(int)(double1/0.0));
assertEquals(-2147483648 ,(int)(-double1/0.0));
assertEquals(0 ,(int)Double.NaN);
}
private static void nanTestFloat() {
float zero = float0;
float NaN = zero / zero;
assertFalse(NaN < NaN);
assertFalse(NaN <= NaN);
assertFalse(NaN == NaN);
assertTrue(NaN != NaN);
assertFalse(NaN >= NaN);
assertFalse(NaN > NaN);
}
private static void nanTestDouble() {
double zero = 0;
double NaN = zero / zero;
assertFalse(NaN < NaN);
assertFalse(NaN <= NaN);
assertFalse(NaN == NaN);
assertTrue(NaN != NaN);
assertFalse(NaN >= NaN);
assertFalse(NaN > NaN);
}
private static void remTest() {
rem(+2, +3);
rem(+2, -3);
rem(-2, +3);
rem(-2, -3);
}
private static void rem(final double a, final double b) {
System.out.println(a + " / " + b + "=" + Long.toHexString(Double.doubleToLongBits(a / b)));
System.out.println(a + " % " + b + "=" + Long.toHexString(Double.doubleToLongBits(a % b)));
System.out.println(a + " rem " + b + "=" + Long.toHexString(Double.doubleToLongBits(Math.IEEEremainder(a, b))));
System.out.println();
}
}