using System; using System.Reflection; /* * Regression tests for the mono JIT. * * Each test needs to be of the form: * * public static int test__ (); * * where is an integer (the value that needs to be returned by * the method to make it pass. * is a user-displayed name used to identify the test. * * The tests can be driven in two ways: * *) running the program directly: Main() uses reflection to find and invoke * the test methods (this is useful mostly to check that the tests are correct) * *) with the --regression switch of the jit (this is the preferred way since * all the tests will be run with optimizations on and off) * * The reflection logic could be moved to a .dll since we need at least another * regression test file written in IL code to have better control on how * the IL code looks. */ #if __MOBILE__ class MathTests #else class Tests #endif { #if !__MOBILE__ public static int Main (string[] args) { return TestDriver.RunTests (typeof (Tests), args); } #endif public static int test_0_sin_precision () { double d1 = Math.Sin (1); double d2 = Math.Sin (1) - d1; return (d2 == 0) ? 0 : 1; } public static int test_0_cos_precision () { double d1 = Math.Cos (1); double d2 = Math.Cos (1) - d1; return (d2 == 0) ? 0 : 1; } public static int test_0_tan_precision () { double d1 = Math.Tan (1); double d2 = Math.Tan (1) - d1; return (d2 == 0) ? 0 : 1; } public static int test_0_atan_precision () { double d1 = Math.Atan (double.NegativeInfinity); double d2 = Math.Atan (double.NegativeInfinity) - d1; return (d2 == 0) ? 0 : 1; } public static int test_0_sqrt_precision () { double d1 = Math.Sqrt (2); double d2 = Math.Sqrt (2) - d1; return (d2 == 0) ? 0 : 1; } public static int test_2_sqrt () { return (int) Math.Sqrt (4); } public static int test_0_sqrt_precision_and_not_spill () { double expected = 0; double[] operands = new double[3]; double[] temporaries = new double[3]; for (int i = 0; i < 3; i++) { operands [i] = (i+1) * (i+1) * (i+1); if (i == 0) { expected = operands [0]; } else { temporaries [i] = operands [i] / expected; temporaries [i] = Math.Sqrt (temporaries [i]); expected = temporaries [i]; } //Console.Write( "{0}: {1}\n", i, temporaries [i] ); } expected = temporaries [2]; double result = Math.Sqrt (operands [2] / Math.Sqrt (operands [1] / operands [0])); //Console.Write( "result: {0,20:G}\n", result ); return (result == expected) ? 0 : 1; } public static int test_0_sqrt_precision_and_spill () { double expected = 0; double[] operands = new double[9]; double[] temporaries = new double[9]; for (int i = 0; i < 9; i++) { operands [i] = (i+1) * (i+1) * (i+1); if (i == 0) { expected = operands [0]; } else { temporaries [i] = operands [i] / expected; temporaries [i] = Math.Sqrt (temporaries [i]); expected = temporaries [i]; } //Console.Write( "{0}: {1}\n", i, temporaries [i] ); } expected = temporaries [8]; double result = Math.Sqrt (operands [8] / Math.Sqrt (operands [7] / Math.Sqrt (operands [6] / Math.Sqrt (operands [5] / Math.Sqrt (operands [4] / Math.Sqrt (operands [3] / Math.Sqrt (operands [2] / Math.Sqrt (operands [1] / operands [0])))))))); //Console.Write( "result: {0,20:G}\n", result ); return (result == expected) ? 0 : 1; } public static int test_0_div_precision_and_spill () { double expected = 0; double[] operands = new double[9]; double[] temporaries = new double[9]; for (int i = 0; i < 9; i++) { operands [i] = (i+1) * (i+1); if (i == 0) { expected = operands [0]; } else { temporaries [i] = operands [i] / expected; expected = temporaries [i]; } //Console.Write( "{0}: {1}\n", i, temporaries [i] ); } expected = temporaries [8]; double result = (operands [8] / (operands [7] / (operands [6] / (operands [5] / (operands [4] / (operands [3] / (operands [2] / (operands [1] / operands [0])))))))); //Console.Write( "result: {0,20:G}\n", result ); return (result == expected) ? 0 : 1; } public static int test_0_sqrt_nan () { return Double.IsNaN (Math.Sqrt (Double.NaN)) ? 0 : 1; } public static int test_0_sin_nan () { return Double.IsNaN (Math.Sin (Double.NaN)) ? 0 : 1; } public static int test_0_cos_nan () { return Double.IsNaN (Math.Cos (Double.NaN)) ? 0 : 1; } public static int test_0_tan_nan () { return Double.IsNaN (Math.Tan (Double.NaN)) ? 0 : 1; } public static int test_0_atan_nan () { return Double.IsNaN (Math.Atan (Double.NaN)) ? 0 : 1; } public static int test_0_min () { if (Math.Min (5, 6) != 5) return 1; if (Math.Min (6, 5) != 5) return 2; if (Math.Min (-100, -101) != -101) return 3; if (Math.Min ((long)5, (long)6) != 5) return 4; if (Math.Min ((long)6, (long)5) != 5) return 5; if (Math.Min ((long)-100, (long)-101) != -101) return 6; return 0; } public static int test_0_max () { if (Math.Max (5, 6) != 6) return 1; if (Math.Max (6, 5) != 6) return 2; if (Math.Max (-100, -101) != -100) return 3; if (Math.Max ((long)5, (long)6) != 6) return 4; if (Math.Max ((long)6, (long)5) != 6) return 5; if (Math.Max ((long)-100, (long)-101) != -100) return 6; return 0; } public static int test_0_min_un () { uint a = (uint)int.MaxValue + 10; for (uint b = 7; b <= 10; ++b) { if (Math.Min (a, b) != b) return (int)b; if (Math.Min (b, a) != b) return (int)b; } if (Math.Min ((ulong)5, (ulong)6) != 5) return 4; if (Math.Min ((ulong)6, (ulong)5) != 5) return 5; ulong la = (ulong)long.MaxValue + 10; for (ulong b = 7; b <= 10; ++b) { if (Math.Min (la, b) != b) return (int)b; if (Math.Min (b, la) != b) return (int)b; } return 0; } public static int test_0_max_un () { uint a = (uint)int.MaxValue + 10; for (uint b = 7; b <= 10; ++b) { if (Math.Max (a, b) != a) return (int)b; if (Math.Max (b, a) != a) return (int)b; } if (Math.Max ((ulong)5, (ulong)6) != 6) return 4; if (Math.Max ((ulong)6, (ulong)5) != 6) return 5; ulong la = (ulong)long.MaxValue + 10; for (ulong b = 7; b <= 10; ++b) { if (Math.Max (la, b) != la) return (int)b; if (Math.Max (b, la) != la) return (int)b; } return 0; } public static int test_0_abs () { double d = -5.0; if (Math.Abs (d) != 5.0) return 1; return 0; } public static int test_0_float_abs () { float f = -1.0f; if (Math.Abs (f) != 1.0f) return 1; return 0; } public static int test_0_round () { if (Math.Round (5.0) != 5.0) return 1; if (Math.Round (5.000000000000001) != 5.0) return 2; if (Math.Round (5.499999999999999) != 5.0) return 3; if (Math.Round (5.5) != 6.0) return 4; if (Math.Round (5.999999999999999) != 6.0) return 5; if (Math.Round (Double.Epsilon) != 0) return 6; if (!Double.IsNaN (Math.Round (Double.NaN))) return 7; if (!Double.IsPositiveInfinity (Math.Round (Double.PositiveInfinity))) return 8; if (!Double.IsNegativeInfinity (Math.Round (Double.NegativeInfinity))) return 9; if (Math.Round (Double.MinValue) != Double.MinValue) return 10; if (Math.Round (Double.MaxValue) != Double.MaxValue) return 11; return 0; } }