/*
* 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.
*
* Alternatively, this file is licensed to You under the MIT License:
* http://opensource.org/licenses/MIT .
*/
package gnu.testlet.vm;
import gnu.testlet.Testlet;
import gnu.testlet.TestHarness;
class TestArithmetic implements Testlet {
public int getExpectedPass() { return 276; }
public int getExpectedFail() { return 0; }
public int getExpectedKnownFail() { return 2; }
TestHarness th;
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;
public void test(TestHarness th) {
this.th = th;
itest();
ltest();
ftest();
dtest();
nanTestFloat();
nanTestDouble();
}
private void itest() {
int a = int3;
th.check(a + 1, 4);
th.check(a - 1, 2);
th.check(a * 3, 9);
th.check(a / 2, 1);
th.check(a % 2, 1);
th.check(-a, -3);
th.check(++a, 4);
a = int_3;
th.check(a + 1, -2);
th.check(a - 1, -4);
th.check(a * 3, -9);
th.check(a / 2, -1);
th.check(a % 2, -1);
th.check(-a, 3);
th.check(++a, -2);
a = int3; // 0x00000011
int b = int5; // 0x00000101
th.check(a & b, 1);
th.check(a | b, 7);
th.check(a ^ b, 6);
a = int_3; // 0xfffffffd;
th.check(a << 1, -6);
th.check(a >> 1, -2);
th.check(a >>> 1, 2147483646);
// funny Java shift cases
a = int1;
th.check(a << 32, 1);
th.check((a << 16) << 16, 0);
th.check(a << 33, 2);
th.check(a << -1, -2147483648);
th.check(a << -32, 1);
th.check(a << -33, -2147483648);
th.check(1 << int33, 2);
th.check(a >> 32, 1);
th.check((a >> 16) >> 16, 0);
th.check(a >> 33, 0);
th.check(a >> -1, 0);
th.check(a >> -32, 1);
th.check(a >> 33, 0);
th.check(-4 >> int33, -2);
th.check(a >>> 32, 1);
th.check((a >>> 16) >>> 16, 0);
th.check(a >>> 33, 0);
th.check(a >>> -1, 0);
th.check(a >>> -32, 1);
th.check(a >>> -33, 0);
th.check(-4 >>> int33, 2147483646);
// IA32 bit test patterns
th.check(((1 << int1) & int3) != 0);
th.check(((1 << int33) & int3) != 0);
th.check((int3 & (1 << int1)) != 0);
th.check((int3 & (1 << int33)) != 0);
th.check(((int3 >> int1) & 1) == 1);
th.check(((int3 >> int33) & 1) == 1);
th.check(((int3 >>> int1) & 1) == 1);
th.check(((int3 >>> int33) & 1) == 1);
// Rotate tests
th.check((int5 << 1)|(int5 >>> -1), 10); // Rotate left by 1
th.check((int5 >>> -1)|(int5 << 1), 10); // Rotate left by 1
th.check((int5 << -1)|(int5 >>> 1), -2147483646); // Rotate right by 1
th.check((int5 >>> 1)|(int5 << -1), -2147483646); // Rotate right by 1
th.check((int5 << int1)|(int5 >>> -int1), 10); // Rotate left by 1
th.check((int5 >>> -int1)|(int5 << int1), 10); // Rotate left by 1
th.check((int5 << -int1)|(int5 >>> int1), -2147483646); // Rotate right by 1
th.check((int5 >>> int1)|(int5 << -int1), -2147483646); // Rotate right by 1
}
private void ltest() {
long a = long10000000000;
long b = long2;
th.check(a + b, 10000000002L);
th.check(a - b, 9999999998L);
th.check(a * b, 20000000000L);
th.check(a / b, 5000000000L);
th.check(a % b, 0);
th.check(-b, -2);
th.check(-a, -10000000000L);
a = long_3;
th.check(a + 2, -1);
th.check(a - 2, -5);
th.check(a * 3, -9);
th.check(a / 2, -1);
th.check(a % 2, -1);
th.check(-a, 3);
a = long0x0110000000000011;
b = long0x1010000000000101;
th.check(a & b, 4503599627370497L);
th.check(a | b, 1229482698272145681L);
th.check(a ^ b, 1224979098644775184L);
// 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;
th.check(a * long0x00000000FFFFFFFF, -4294967295L);
th.check(a * long0xFFFFFFFF00000000, 4294967296L);
th.check(a * long0x00000001FFFFFFFF, -8589934591L);
th.check(a * long0xFFFFFFFF00000001, 4294967295L);
th.check(a * long0x0000000100000000, -4294967296L);
th.check(a * long0x0000000100000001, -4294967297L);
th.check(a & long0x00000000FFFFFFFF, 4294967295L);
th.check(a & long0xFFFFFFFF00000000, -4294967296L);
th.check(a & long0x00000001FFFFFFFF, 8589934591L);
th.check(a & long0xFFFFFFFF00000001, -4294967295L);
th.check(a & long0x0000000100000000, 4294967296L);
th.check(a & long0x0000000100000001, 4294967297L);
a = long0;
th.check(a | long0x00000000FFFFFFFF, 4294967295L);
th.check(a | long0xFFFFFFFF00000000, -4294967296L);
th.check(a | long0x00000001FFFFFFFF, 8589934591L);
th.check(a | long0xFFFFFFFF00000001, -4294967295L);
th.check(a | long0x0000000100000001, 4294967297L);
th.check(a ^ long0x00000000FFFFFFFF, 4294967295L);
th.check(a ^ long0xFFFFFFFF00000000, -4294967296L);
th.check(a ^ long0x00000001FFFFFFFF, 8589934591L);
th.check(a ^ long0xFFFFFFFF00000001, -4294967295L);
th.check(a ^ long0x0000000100000001, 4294967297L);
a = long0xBEEFBEEFCAFEBABE;
th.check(a << 1, 9070106573795063164L);
th.check(a << 2, -306530926119425288L);
th.check(a << 3, -613061852238850576L);
th.check(a << 4, -1226123704477701152L);
th.check(a << 8, -1171235197933666816L);
th.check(a << 16, -4688305491665879040L);
th.check(a << 32, -3819410108757049344L);
th.check(a << 33, -7638820217514098688L);
th.check(a << 34, 3169103638681354240L);
th.check(a << 35, 6338207277362708480L);
th.check(a << 36, -5770329518984134656L);
th.check(a << 40, -91551935198396416L);
th.check(a << 48, -4990551337079930880L);
th.check(a << 56, -4755801206503243776L);
th.check(a << 63, 0L);
th.check(a << 64, -4688318749957244226L);
th.check(a << 65, 9070106573795063164L);
th.check(a << int65, 9070106573795063164L);
th.check(a >> 1, -2344159374978622113L);
th.check(a >> 2, -1172079687489311057L);
th.check(a >> 3, -586039843744655529L);
th.check(a >> 4, -293019921872327765L);
th.check(a >> 8, -18313745117020486L);
th.check(a >> 16, -71538066863362L);
th.check(a >> 32, -1091584273L);
th.check(a >> 33, -545792137L);
th.check(a >> 34, -272896069L);
th.check(a >> 35, -136448035L);
th.check(a >> 36, -68224018L);
th.check(a >> 40, -4264002L);
th.check(a >> 48, -16657L);
th.check(a >> 56, -66L);
th.check(a >> 63, -1L);
th.check(a >> 64, -4688318749957244226L);
th.check(a >> 65, -2344159374978622113L);
th.check(a >> int65, -2344159374978622113L);
th.check(a >>> 1, 6879212661876153695L);
th.check(a >>> 2, 3439606330938076847L);
th.check(a >>> 3, 1719803165469038423L);
th.check(a >>> 4, 859901582734519211L);
th.check(a >>> 8, 53743848920907450L);
th.check(a >>> 16, 209936909847294L);
th.check(a >>> 32, 3203383023L);
th.check(a >>> 33, 1601691511L);
th.check(a >>> 34, 800845755L);
th.check(a >>> 35, 400422877L);
th.check(a >>> 36, 200211438L);
th.check(a >>> 40, 12513214L);
th.check(a >>> 48, 48879L);
th.check(a >>> 56, 190L);
th.check(a >>> 63, 1L);
th.check(a >>> 64, -4688318749957244226L);
th.check(a >>> 65, 6879212661876153695L);
th.check(a >>> int65, 6879212661876153695L);
}
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 void checkFloatToInt(float val1, int val2) {
th.check((int)val1, val2);
}
private void checkIntToFloat(int val1, float val2) {
th.check((float)val1, val2);
}
private void checkIntToFloatRel(int val1, float val2) {
th.check(Math.abs((float)val1 - val2) / val2 < 1E-9);
}
private void checkDoubleToInt(double val1, int val2) {
th.check((int)val1, val2);
}
private void checkIntToDouble(int val1, double val2) {
th.check((double)val1, val2);
}
private void checkFloatToLong(float val1, long val2) {
th.check((long)val1, val2);
}
private void checkLongToFloat(long val1, float val2) {
th.check((float)val1, val2);
}
private void todoFloatToLong(float val1, long val2) {
th.todo((long)val1, val2);
}
private void checkDoubleToLong(double val1, long val2) {
th.check((long)val1, val2);
}
private void checkLongToDouble(long val1, double val2) {
th.check((double)val1, val2);
}
private void ftest() {
// f2i, d2i, f2l and d2l tests
checkFloatToInt(float0, 0);
checkFloatToInt(float1, 1);
checkDoubleToInt(double0, 0);
checkDoubleToInt(double1, 1);
checkFloatToInt(Float.NaN, 0);
checkFloatToInt(-Float.NaN, 0);
checkDoubleToInt(Double.NaN, 0);
checkDoubleToInt(-Double.NaN, 0);
checkFloatToInt(Float.POSITIVE_INFINITY, 2147483647);
checkFloatToInt(Float.NEGATIVE_INFINITY, -2147483648);
checkFloatToInt(float_maxint, 2147483647);
checkFloatToInt(float_minint, -2147483648);
checkDoubleToInt(double_maxint, 2147483647);
checkDoubleToInt(double_minint, -2147483648);
checkIntToFloat(0, float0);
checkIntToFloat(1, float1);
checkIntToDouble(0, double0);
checkIntToDouble(1, double1);
checkIntToFloatRel(2147483647, (float)2.14748365E9);
checkIntToFloat(-2147483648, (float)-2.14748365E9);
checkIntToFloatRel(2147483647, float_maxint);
checkIntToFloat(-2147483648, float_minint);
checkIntToDouble(2147483647, double_maxint);
checkIntToDouble(-2147483648, double_minint);
checkFloatToLong(float0, 0L);
checkFloatToLong(float1, 1L);
checkDoubleToLong(double0, 0L);
checkDoubleToLong(double1, 1L);
checkFloatToLong(Float.NaN, 0L);
checkFloatToLong(-Float.NaN, 0L);
checkDoubleToLong(Double.NaN, 0L);
checkDoubleToLong(-Double.NaN, 0L);
todoFloatToLong(Float.POSITIVE_INFINITY, 9223372036854775807L);
todoFloatToLong(Float.NEGATIVE_INFINITY, -9223372036854775808L);
checkFloatToLong(float_maxlong, 9223372036854775807L);
checkFloatToLong(float_minlong, -9223372036854775808L);
checkDoubleToLong(double_maxlong, 9223372036854775807L);
checkDoubleToLong(double_minlong, -9223372036854775808L);
checkLongToFloat(0L, float0);
checkLongToFloat(1L, float1);
checkLongToDouble(0L, double0);
checkLongToDouble(1L, double1);
checkLongToFloat(9223372036854775807L, (float)9.223372E18);
checkLongToFloat(-9223372036854775808L, (float)-9.223372E18);
checkLongToFloat(9223372036854775807L, float_maxlong);
checkLongToFloat(-9223372036854775808L, float_minlong);
checkLongToDouble(9223372036854775807L, double_maxlong);
checkLongToDouble(-9223372036854775808L, double_minlong);
float a = float1;
float b = float2;
th.check(Integer.toHexString(Float.floatToIntBits(a + b)), Integer.toHexString(Float.floatToIntBits(3.0F))); // fadd
th.check(Integer.toHexString(Float.floatToIntBits(a - b)), Integer.toHexString(Float.floatToIntBits(-1.0F))); // fsub
th.check(Integer.toHexString(Float.floatToIntBits(a * b)), Integer.toHexString(Float.floatToIntBits(2.0F))); // fmul
th.check(Integer.toHexString(Float.floatToIntBits(a / b)), Integer.toHexString(Float.floatToIntBits(0.5F))); // fdiv
th.check(Integer.toHexString(Float.floatToIntBits(-a)), Integer.toHexString(Float.floatToIntBits(-1.0F))); // fneg
a = float1_5;
b = float0_9;
th.check(Integer.toHexString(Float.floatToIntBits(a % b)), Integer.toHexString(Float.floatToIntBits(0.6F))); // frem
th.check(String.valueOf(float0/float0), "NaN");
th.check(String.valueOf(Float.NaN + Float.NaN), "NaN");
th.check(String.valueOf(Float.NaN + float2), "NaN");
th.check(String.valueOf(Float.NaN * float2), "NaN");
th.check(String.valueOf((float0 / 0.0) * Float.POSITIVE_INFINITY), "NaN");
th.check(String.valueOf((float1 / 0.0) * 0.0), "NaN");
th.check(String.valueOf((float1 / 0.0) - (float1 / 0.0)), "NaN");
th.check(String.valueOf((float1 / 0.0) / (float1 / 0.0)), "NaN");
th.check(String.valueOf((-float1 / 0.0) * 0.0), "NaN");
th.check(String.valueOf((-float1 / 0.0) - (-float1 / 0.0)), "NaN");
th.check(!(Float.NaN > float1));
th.check(!(Float.NaN < float1));
th.check(Float.NaN != float1);
th.check(Float.NaN != -float1);
th.check(!(Float.NaN > Float.POSITIVE_INFINITY));
th.check(!(Float.NaN < Float.POSITIVE_INFINITY));
th.check(Float.POSITIVE_INFINITY == Float.POSITIVE_INFINITY);
th.check(-Float.POSITIVE_INFINITY == Float.NEGATIVE_INFINITY);
th.check(Float.NEGATIVE_INFINITY < float1);
th.check((-float1/0.0) == (-float1/0.0));
th.check(float1/0.0, Float.POSITIVE_INFINITY);
th.check((float1/0.0) + 2.0, Float.POSITIVE_INFINITY);
th.check((float1/0.0) * 0.5, Float.POSITIVE_INFINITY);
th.check((float1/0.0) + (float1/0.0), Float.POSITIVE_INFINITY);
th.check((float1/0.0) * (float1/0.0), Float.POSITIVE_INFINITY);
th.check(Math.abs(-float1/0.0), Float.POSITIVE_INFINITY);
th.check(-float1/0.0, Float.NEGATIVE_INFINITY);
th.check((-float1/0.0) + 2.0, Float.NEGATIVE_INFINITY);
th.check((-float1/0.0) * 0.5, Float.NEGATIVE_INFINITY);
th.check((int)(float1/0.0), 2147483647);
th.check((int)(-float1/0.0), -2147483648);
}
private void dtest() {
double a = 1;
double b = 2;
th.check(Double.doubleToLongBits(a + b), Double.doubleToLongBits(3.0D)); // dadd
th.check(Double.doubleToLongBits(a - b), Double.doubleToLongBits(-1.0D)); // dsub
th.check(Double.doubleToLongBits(a * b), Double.doubleToLongBits(2.0D)); // dmul
th.check(Double.doubleToLongBits(a / b), Double.doubleToLongBits(0.5D)); // ddiv
th.check(Double.doubleToLongBits(-a), Double.doubleToLongBits(-1.0D)); // dneg
a = 1.5;
b = 0.9;
th.check(Double.doubleToLongBits(a % b), Double.doubleToLongBits(0.6D)); // drem
th.check(String.valueOf(double0/double0), "NaN");
th.check(String.valueOf(Double.NaN + Double.NaN), "NaN");
th.check(String.valueOf(Double.NaN + double2), "NaN");
th.check(String.valueOf(Double.NaN * double2), "NaN");
th.check(String.valueOf((double0 / 0.0) * Double.POSITIVE_INFINITY), "NaN");
th.check(String.valueOf((double1 / 0.0) * 0.0), "NaN");
th.check(String.valueOf((double1 / 0.0) - (double1 / 0.0)), "NaN");
th.check(String.valueOf((double1 / 0.0) / (double1 / 0.0)), "NaN");
th.check(String.valueOf((-double1 / 0.0) * 0.0), "NaN");
th.check(String.valueOf((-double1 / 0.0) - (-double1 / 0.0)), "NaN");
th.check(!(Double.NaN > double1));
th.check(!(Double.NaN < double1));
th.check(Double.NaN != double1);
th.check(Double.NaN != -double1);
th.check(!(Double.NaN > Double.POSITIVE_INFINITY));
th.check(!(Double.NaN < Double.POSITIVE_INFINITY));
th.check(Double.POSITIVE_INFINITY == Double.POSITIVE_INFINITY);
th.check(-Double.POSITIVE_INFINITY == Double.NEGATIVE_INFINITY);
th.check(Double.NEGATIVE_INFINITY < double1);
th.check((-double1/0.0) == (-double1/0.0));
th.check(double1/0.0, Double.POSITIVE_INFINITY);
th.check((double1/0.0) + 2.0, Double.POSITIVE_INFINITY);
th.check((double1/0.0) * 0.5, Double.POSITIVE_INFINITY);
th.check((double1/0.0) + (double1/0.0), Double.POSITIVE_INFINITY);
th.check((double1/0.0) * (double1/0.0), Double.POSITIVE_INFINITY);
th.check(Math.abs(-double1/0.0), Double.POSITIVE_INFINITY);
th.check(-double1/0.0, Double.NEGATIVE_INFINITY);
th.check((-double1/0.0) + 2.0, Double.NEGATIVE_INFINITY);
th.check((-double1/0.0) * 0.5, Double.NEGATIVE_INFINITY);
th.check((int)(double1/0.0), 2147483647);
th.check((int)(-double1/0.0), -2147483648);
th.check((int)Double.NaN, 0);
}
private void nanTestFloat() {
float zero = float0;
float NaN = zero / zero;
th.check(!(NaN < NaN));
th.check(NaN != NaN);
th.check(!(NaN > NaN));
}
private void nanTestDouble() {
double zero = 0;
double NaN = zero / zero;
th.check(!(NaN < NaN));
th.check(NaN != NaN);
th.check(!(NaN > NaN));
}
}