From 1bb6d1b74ab6f89e6b1d07963b7dc8dcbd4802a8 Mon Sep 17 00:00:00 2001 From: Jetro Lauha Date: Tue, 4 May 2021 17:19:19 +0300 Subject: [PATCH 1/3] Small tweaks for GetHashCode() - F32: use the raw value as is - F64: fold using xor instead of or --- Examples/FixMath/F32.cs | 2 +- Examples/FixMath/F64.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Examples/FixMath/F32.cs b/Examples/FixMath/F32.cs index 4a8e666..af7873e 100644 --- a/Examples/FixMath/F32.cs +++ b/Examples/FixMath/F32.cs @@ -228,7 +228,7 @@ public override string ToString() public override int GetHashCode() { - return (int)Raw | (int)(Raw >> 32); + return Raw; } } } diff --git a/Examples/FixMath/F64.cs b/Examples/FixMath/F64.cs index 8744d03..12f0842 100644 --- a/Examples/FixMath/F64.cs +++ b/Examples/FixMath/F64.cs @@ -251,7 +251,7 @@ public override string ToString() public override int GetHashCode() { - return (int)Raw | (int)(Raw >> 32); + return (int)Raw ^ (int)(Raw >> 32); } } } From 3265041881cab1467cc0446039d1a2c70e1a6930 Mon Sep 17 00:00:00 2001 From: Jetro Lauha Date: Fri, 7 May 2021 20:52:33 +0300 Subject: [PATCH 2/3] Replaced broken link to Hacker's Delight with archive.org version --- FixPointCS/Fixed64.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FixPointCS/Fixed64.cs b/FixPointCS/Fixed64.cs index 46255aa..1e8a57c 100644 --- a/FixPointCS/Fixed64.cs +++ b/FixPointCS/Fixed64.cs @@ -363,7 +363,7 @@ private static int Nlz(ulong x) /// public static long DivPrecise(long arg_a, long arg_b) { - // From http://www.hackersdelight.org/hdcodetxt/divlu.c.txt + // From https://web.archive.org/web/20190109053731/http://www.hackersdelight.org/hdcodetxt/divlu.c.txt #if JAVA long sign_dif = arg_a ^ arg_b; From c4f8980b31e799ce22479cf348d193151a39e5da Mon Sep 17 00:00:00 2001 From: Jetro Lauha Date: Sat, 24 Sep 2022 18:56:52 +0300 Subject: [PATCH 3/3] Added support for disabling runtime validation: #define DISABLE_RUNTIME_VALIDATION When used, code for Asserts and InvalidArgument calls will be left out. --- FixPointCS/Fixed32.cs | 120 +++++++++++++++++++++++++++++++++++++ FixPointCS/Fixed64.cs | 128 ++++++++++++++++++++++++++++++++++++++++ FixPointCS/FixedUtil.cs | 4 ++ 3 files changed, 252 insertions(+) diff --git a/FixPointCS/Fixed32.cs b/FixPointCS/Fixed32.cs index 24a43cf..0a0b6a6 100644 --- a/FixPointCS/Fixed32.cs +++ b/FixPointCS/Fixed32.cs @@ -22,6 +22,8 @@ // SOFTWARE. // +//#define DISABLE_RUNTIME_VALIDATION + // PREFIX #if CPP #elif JAVA @@ -357,7 +359,9 @@ public static int Div(int a, int b) { if (b == MinValue || b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Div", "b", b); +#endif return 0; } @@ -371,7 +375,9 @@ public static int DivFast(int a, int b) { if (b == MinValue || b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.DivFast", "b", b); +#endif return 0; } @@ -400,7 +406,9 @@ public static int DivFastest(int a, int b) { if (b == MinValue || b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.DivFastest", "b", b); +#endif return 0; } @@ -429,7 +437,9 @@ public static int Mod(int a, int b) { if (b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Mod", "b", b); +#endif return 0; } @@ -444,8 +454,10 @@ public static int SqrtPrecise(int a) // Adapted from https://github.com/chmike/fpsqrt if (a <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (a < 0) FixedUtil.InvalidArgument("Fixed32.SqrtPrecise", "a", a); +#endif return 0; } @@ -491,8 +503,10 @@ public static int Sqrt(int x) // Return 0 for all non-positive values. if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed32.Sqrt", "x", x); +#endif return 0; } @@ -503,7 +517,9 @@ public static int Sqrt(int x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 15 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset - 14); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.SqrtPoly3Lut8(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -520,8 +536,10 @@ public static int SqrtFast(int x) // Return 0 for all non-positive values. if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed32.SqrtFast", "x", x); +#endif return 0; } @@ -549,8 +567,10 @@ public static int SqrtFastest(int x) // Return 0 for all non-positive values. if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed32.SqrtFastest", "x", x); +#endif return 0; } @@ -561,7 +581,9 @@ public static int SqrtFastest(int x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 15 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset - 14); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.SqrtPoly3(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -581,7 +603,9 @@ public static int RSqrt(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.RSqrt", "x", x); +#endif return 0; } @@ -592,7 +616,9 @@ public static int RSqrt(int x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 1 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.RSqrtPoly3Lut16(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -612,7 +638,9 @@ public static int RSqrtFast(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.RSqrtFast", "x", x); +#endif return 0; } @@ -623,7 +651,9 @@ public static int RSqrtFast(int x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 1 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.RSqrtPoly5(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -643,7 +673,9 @@ public static int RSqrtFastest(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.RSqrtFastest", "x", x); +#endif return 0; } @@ -654,7 +686,9 @@ public static int RSqrtFastest(int x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 1 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.RSqrtPoly3(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -673,7 +707,9 @@ public static int Rcp(int x) { if (x == MinValue || x == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Rcp", "x", x); +#endif return 0; } @@ -685,7 +721,9 @@ public static int Rcp(int x) int offset = 29 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset - 28); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly4Lut8(n - ONE); @@ -701,7 +739,9 @@ public static int RcpFast(int x) { if (x == MinValue || x == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.RcpFast", "x", x); +#endif return 0; } @@ -713,7 +753,9 @@ public static int RcpFast(int x) int offset = 29 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset - 28); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly6(n - ONE); @@ -730,7 +772,9 @@ public static int RcpFastest(int x) { if (x == MinValue || x == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.RcpFastest", "x", x); +#endif return 0; } @@ -742,7 +786,9 @@ public static int RcpFastest(int x) int offset = 29 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset - 28); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly4(n - ONE); @@ -829,7 +875,9 @@ public static int Log(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Log", "x", x); +#endif return 0; } @@ -839,7 +887,9 @@ public static int Log(int x) // Polynomial approximation. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.LogPoly5Lut8(n - ONE); // Combine integer and fractional parts (into s16.16). @@ -851,7 +901,9 @@ public static int LogFast(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.LogFast", "x", x); +#endif return 0; } @@ -861,7 +913,9 @@ public static int LogFast(int x) // Polynomial approximation. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.LogPoly3Lut8(n - ONE); // Combine integer and fractional parts (into s16.16). @@ -873,7 +927,9 @@ public static int LogFastest(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.LogFastest", "x", x); +#endif return 0; } @@ -883,7 +939,9 @@ public static int LogFastest(int x) // Polynomial approximation. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.LogPoly5(n - ONE); // Combine integer and fractional parts (into s16.16). @@ -895,7 +953,9 @@ public static int Log2(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Log2", "x", x); +#endif return 0; } @@ -905,7 +965,9 @@ public static int Log2(int x) // Polynomial approximation of mantissa. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.Log2Poly4Lut16(n - ONE); // Combine integer and fractional parts (into s16.16). @@ -917,7 +979,9 @@ public static int Log2Fast(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Log2Fast", "x", x); +#endif return 0; } @@ -927,7 +991,9 @@ public static int Log2Fast(int x) // Polynomial approximation of mantissa. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.Log2Poly3Lut16(n - ONE); // Combine integer and fractional parts (into s16.16). @@ -939,7 +1005,9 @@ public static int Log2Fastest(int x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Log2Fastest", "x", x); +#endif return 0; } @@ -949,7 +1017,9 @@ public static int Log2Fastest(int x) // Polynomial approximation of mantissa. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.Log2Poly5(n - ONE); // Combine integer and fractional parts (into s16.16). @@ -968,8 +1038,10 @@ public static int Pow(int x, int exponent) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed32.Pow", "x", x); +#endif return 0; } @@ -988,8 +1060,10 @@ public static int PowFast(int x, int exponent) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed32.PowFast", "x", x); +#endif return 0; } @@ -1008,8 +1082,10 @@ public static int PowFastest(int x, int exponent) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed32.PowFastest", "x", x); +#endif return 0; } @@ -1027,8 +1103,10 @@ private static int UnitSin(int z) z = (1 << 31) - z; // Now z is in range [-1, 1]. +#if !DISABLE_RUNTIME_VALIDATION const int ONE = (1 << 30); Debug.Assert((z >= -ONE) && (z <= ONE)); +#endif // Polynomial approximation. int zz = FixedUtil.Qmul30(z, z); @@ -1049,8 +1127,10 @@ private static int UnitSinFast(int z) z = (1 << 31) - z; // Now z is in range [-1, 1]. +#if !DISABLE_RUNTIME_VALIDATION const int ONE = (1 << 30); Debug.Assert((z >= -ONE) && (z <= ONE)); +#endif // Polynomial approximation. int zz = FixedUtil.Qmul30(z, z); @@ -1071,8 +1151,10 @@ private static int UnitSinFastest(int z) z = (1 << 31) - z; // Now z is in range [-1, 1]. +#if !DISABLE_RUNTIME_VALIDATION const int ONE = (1 << 30); Debug.Assert((z >= -ONE) && (z <= ONE)); +#endif // Polynomial approximation. int zz = FixedUtil.Qmul30(z, z); @@ -1156,18 +1238,26 @@ public static int TanFastest(int x) private static int Atan2Div(int y, int x) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(y >= 0 && x > 0 && x >= y); +#endif // Normalize input into [1.0, 2.0( range (convert to s2.30). const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION const int HALF = (1 << 29); +#endif int offset = 1 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation of reciprocal. int oox = FixedUtil.RcpPoly4Lut8(n - ONE); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(oox >= HALF && oox <= ONE); +#endif // Apply exponent and multiply. int yr = FixedUtil.ShiftRight(y, offset); @@ -1183,7 +1273,9 @@ public static int Atan2(int y, int x) if (y > 0) return PiHalf; if (y < 0) return -PiHalf; +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Atan2", "y, x", y, x); +#endif return 0; } @@ -1211,17 +1303,23 @@ public static int Atan2(int y, int x) private static int Atan2DivFast(int y, int x) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(y >= 0 && x > 0 && x >= y); +#endif // Normalize input into [1.0, 2.0( range (convert to s2.30). const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION const int HALF = (1 << 29); +#endif int offset = 1 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset); // Polynomial approximation. int oox = FixedUtil.RcpPoly6(n - ONE); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(oox >= HALF && oox <= ONE); +#endif // Apply exponent and multiply. int yr = FixedUtil.ShiftRight(y, offset); @@ -1237,7 +1335,9 @@ public static int Atan2Fast(int y, int x) if (y > 0) return PiHalf; if (y < 0) return -PiHalf; +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Atan2Fast", "y, x", y, x); +#endif return 0; } @@ -1265,17 +1365,23 @@ public static int Atan2Fast(int y, int x) private static int Atan2DivFastest(int y, int x) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(y >= 0 && x > 0 && x >= y); +#endif // Normalize input into [1.0, 2.0( range (convert to s2.30). const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION const int HALF = (1 << 29); +#endif int offset = 1 - Nlz((uint)x); int n = FixedUtil.ShiftRight(x, offset); // Polynomial approximation. int oox = FixedUtil.RcpPoly4(n - ONE); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(oox >= HALF && oox <= ONE); +#endif // Apply exponent and multiply. int yr = FixedUtil.ShiftRight(y, offset); @@ -1291,7 +1397,9 @@ public static int Atan2Fastest(int y, int x) if (y > 0) return PiHalf; if (y < 0) return -PiHalf; +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Atan2Fastest", "y, x", y, x); +#endif return 0; } @@ -1322,7 +1430,9 @@ public static int Asin(int x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Asin", "x", x); +#endif return 0; } @@ -1337,7 +1447,9 @@ public static int AsinFast(int x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.AsinFast", "x", x); +#endif return 0; } @@ -1352,7 +1464,9 @@ public static int AsinFastest(int x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.AsinFastest", "x", x); +#endif return 0; } @@ -1367,7 +1481,9 @@ public static int Acos(int x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.Acos", "x", x); +#endif return 0; } @@ -1382,7 +1498,9 @@ public static int AcosFast(int x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.AcosFast", "x", x); +#endif return 0; } @@ -1397,7 +1515,9 @@ public static int AcosFastest(int x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed32.AcosFastest", "x", x); +#endif return 0; } diff --git a/FixPointCS/Fixed64.cs b/FixPointCS/Fixed64.cs index 1e242f7..443ce16 100644 --- a/FixPointCS/Fixed64.cs +++ b/FixPointCS/Fixed64.cs @@ -22,6 +22,8 @@ // SOFTWARE. // +//#define DISABLE_RUNTIME_VALIDATION + // PREFIX #if CPP #elif JAVA @@ -314,7 +316,9 @@ public static long Mul(long a, long b) [MethodImpl(FixedUtil.AggressiveInlining)] private static int MulIntLongLow(int a, long b) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(a >= 0); +#endif int bi = (int)(b >> Shift); long bf = b & FractionMask; return (int)FixedUtil.LogicalShiftRight(a * bf, Shift) + a * bi; @@ -323,7 +327,9 @@ private static int MulIntLongLow(int a, long b) [MethodImpl(FixedUtil.AggressiveInlining)] private static long MulIntLongLong(int a, long b) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(a >= 0); +#endif long bi = b >> Shift; long bf = b & FractionMask; return FixedUtil.LogicalShiftRight(a * bf, Shift) + a * bi; @@ -504,7 +510,9 @@ public static long Div(long a, long b) { if (b == MinValue || b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Div", "b", b); +#endif return 0; } @@ -516,7 +524,9 @@ public static long Div(long a, long b) int offset = 31 - Nlz((ulong)b); int n = (int)FixedUtil.ShiftRight(b, offset + 2); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly4Lut8(n - ONE); @@ -533,7 +543,9 @@ public static long DivFast(long a, long b) { if (b == MinValue || b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.DivFast", "b", b); +#endif return 0; } @@ -545,7 +557,9 @@ public static long DivFast(long a, long b) int offset = 31 - Nlz((ulong)b); int n = (int)FixedUtil.ShiftRight(b, offset + 2); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly6(n - ONE); @@ -562,7 +576,9 @@ public static long DivFastest(long a, long b) { if (b == MinValue || b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.DivFastest", "b", b); +#endif return 0; } @@ -574,7 +590,9 @@ public static long DivFastest(long a, long b) int offset = 31 - Nlz((ulong)b); int n = (int)FixedUtil.ShiftRight(b, offset + 2); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly4(n - ONE); @@ -591,7 +609,9 @@ public static long Mod(long a, long b) { if (b == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Mod", "b", b); +#endif return 0; } @@ -606,8 +626,10 @@ public static long SqrtPrecise(long a) // Adapted from https://github.com/chmike/fpsqrt if (a <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (a < 0) FixedUtil.InvalidArgument("Fixed64.SqrtPrecise", "a", a); +#endif return 0; } @@ -653,8 +675,10 @@ public static long Sqrt(long x) // Return 0 for all non-positive values. if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed64.Sqrt", "x", x); +#endif return 0; } @@ -665,7 +689,9 @@ public static long Sqrt(long x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.SqrtPoly3Lut8(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -682,8 +708,10 @@ public static long SqrtFast(long x) // Return 0 for all non-positive values. if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed64.SqrtFast", "x", x); +#endif return 0; } @@ -694,7 +722,9 @@ public static long SqrtFast(long x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.SqrtPoly4(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -711,8 +741,10 @@ public static long SqrtFastest(long x) // Return 0 for all non-positive values. if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed64.SqrtFastest", "x", x); +#endif return 0; } @@ -723,7 +755,9 @@ public static long SqrtFastest(long x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.SqrtPoly3(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -743,7 +777,9 @@ public static long RSqrt(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.RSqrt", "x", x); +#endif return 0; } @@ -754,7 +790,9 @@ public static long RSqrt(long x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.RSqrtPoly3Lut16(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -774,7 +812,9 @@ public static long RSqrtFast(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.RSqrtFast", "x", x); +#endif return 0; } @@ -785,7 +825,9 @@ public static long RSqrtFast(long x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.RSqrtPoly5(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -805,7 +847,9 @@ public static long RSqrtFastest(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.RSqrtFastest", "x", x); +#endif return 0; } @@ -816,7 +860,9 @@ public static long RSqrtFastest(long x) // Normalize input into [1.0, 2.0( range (as s2.30). int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif int y = FixedUtil.RSqrtPoly3(n - ONE); // Divide offset by 2 (to get sqrt), compute adjust value for odd exponents. @@ -835,7 +881,9 @@ public static long Rcp(long x) { if (x == MinValue || x == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Rcp", "x", x); +#endif return 0; } @@ -847,7 +895,9 @@ public static long Rcp(long x) int offset = 31 - Nlz((ulong)x); int n = (int)FixedUtil.ShiftRight(x, offset + 2); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly4Lut8(n - ONE); @@ -864,7 +914,9 @@ public static long RcpFast(long x) { if (x == MinValue || x == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.RcpFast", "x", x); +#endif return 0; } @@ -876,7 +928,9 @@ public static long RcpFast(long x) int offset = 31 - Nlz((ulong)x); int n = (int)FixedUtil.ShiftRight(x, offset + 2); const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif // Polynomial approximation. int res = FixedUtil.RcpPoly6(n - ONE); @@ -893,7 +947,9 @@ public static long RcpFastest(long x) { if (x == MinValue || x == 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.RcpFastest", "x", x); +#endif return 0; } @@ -993,7 +1049,9 @@ public static long Log(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Log", "x", x); +#endif return 0; } @@ -1001,7 +1059,9 @@ public static long Log(long x) const int ONE = (1 << 30); int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif long y = (long)FixedUtil.LogPoly5Lut8(n - ONE) << 2; // Combine integer and fractional parts (into s32.32). @@ -1013,7 +1073,9 @@ public static long LogFast(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.LogFast", "x", x); +#endif return 0; } @@ -1021,7 +1083,9 @@ public static long LogFast(long x) const int ONE = (1 << 30); int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif long y = (long)FixedUtil.LogPoly3Lut8(n - ONE) << 2; // Combine integer and fractional parts (into s32.32). @@ -1033,7 +1097,9 @@ public static long LogFastest(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.LogFastest", "x", x); +#endif return 0; } @@ -1041,7 +1107,9 @@ public static long LogFastest(long x) const int ONE = (1 << 30); int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif long y = (long)FixedUtil.LogPoly5(n - ONE) << 2; // Combine integer and fractional parts (into s32.32). @@ -1053,7 +1121,9 @@ public static long Log2(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Log2", "x", x); +#endif return 0; } @@ -1063,7 +1133,9 @@ public static long Log2(long x) // Polynomial approximation of mantissa. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif long y = (long)FixedUtil.Log2Poly4Lut16(n - ONE) << 2; // Combine integer and fractional parts (into s32.32). @@ -1075,7 +1147,9 @@ public static long Log2Fast(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Log2Fast", "x", x); +#endif return 0; } @@ -1085,7 +1159,9 @@ public static long Log2Fast(long x) // Polynomial approximation of mantissa. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif long y = (long)FixedUtil.Log2Poly3Lut16(n - ONE) << 2; // Combine integer and fractional parts (into s32.32). @@ -1097,7 +1173,9 @@ public static long Log2Fastest(long x) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Log2Fastest", "x", x); +#endif return 0; } @@ -1107,7 +1185,9 @@ public static long Log2Fastest(long x) // Polynomial approximation of mantissa. const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(n >= ONE); +#endif long y = (long)FixedUtil.Log2Poly5(n - ONE) << 2; // Combine integer and fractional parts (into s32.32). @@ -1126,8 +1206,10 @@ public static long Pow(long x, long exponent) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed64.Pow", "x", x); +#endif return 0; } @@ -1146,8 +1228,10 @@ public static long PowFast(long x, long exponent) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed64.PowFast", "x", x); +#endif return 0; } @@ -1166,8 +1250,10 @@ public static long PowFastest(long x, long exponent) // Return 0 for invalid values if (x <= 0) { +#if !DISABLE_RUNTIME_VALIDATION if (x < 0) FixedUtil.InvalidArgument("Fixed64.PowFastest", "x", x); +#endif return 0; } @@ -1185,8 +1271,10 @@ private static int UnitSin(int z) z = (1 << 31) - z; // Now z is in range [-1, 1]. +#if !DISABLE_RUNTIME_VALIDATION const int ONE = (1 << 30); Debug.Assert((z >= -ONE) && (z <= ONE)); +#endif // Polynomial approximation. int zz = FixedUtil.Qmul30(z, z); @@ -1207,8 +1295,10 @@ private static int UnitSinFast(int z) z = (1 << 31) - z; // Now z is in range [-1, 1]. +#if !DISABLE_RUNTIME_VALIDATION const int ONE = (1 << 30); Debug.Assert((z >= -ONE) && (z <= ONE)); +#endif // Polynomial approximation. int zz = FixedUtil.Qmul30(z, z); @@ -1229,8 +1319,10 @@ private static int UnitSinFastest(int z) z = (1 << 31) - z; // Now z is in range [-1, 1]. +#if !DISABLE_RUNTIME_VALIDATION const int ONE = (1 << 30); Debug.Assert((z >= -ONE) && (z <= ONE)); +#endif // Polynomial approximation. int zz = FixedUtil.Qmul30(z, z); @@ -1314,18 +1406,24 @@ public static long TanFastest(long x) private static int Atan2Div(long y, long x) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(y >= 0 && x > 0 && x >= y); +#endif // Normalize input into [1.0, 2.0( range (convert to s2.30). const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION const int HALF = (1 << 29); +#endif int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); int k = n - ONE; // Polynomial approximation of reciprocal. int oox = FixedUtil.RcpPoly4Lut8(k); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(oox >= HALF && oox <= ONE); +#endif // Apply exponent and multiply. long yr = (offset >= 0) ? (y >> offset) : (y << -offset); @@ -1341,7 +1439,9 @@ public static long Atan2(long y, long x) if (y > 0) return PiHalf; if (y < 0) return -PiHalf; +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Atan2", "y, x", y, x); +#endif return 0; } @@ -1370,18 +1470,24 @@ public static long Atan2(long y, long x) private static int Atan2DivFast(long y, long x) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(y >= 0 && x > 0 && x >= y); +#endif // Normalize input into [1.0, 2.0( range (convert to s2.30). const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION const int HALF = (1 << 29); +#endif int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); int k = n - ONE; // Polynomial approximation. int oox = FixedUtil.RcpPoly6(k); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(oox >= HALF && oox <= ONE); +#endif // Apply exponent and multiply. long yr = (offset >= 0) ? (y >> offset) : (y << -offset); @@ -1397,7 +1503,9 @@ public static long Atan2Fast(long y, long x) if (y > 0) return PiHalf; if (y < 0) return -PiHalf; +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Atan2Fast", "y, x", y, x); +#endif return 0; } @@ -1426,18 +1534,24 @@ public static long Atan2Fast(long y, long x) private static int Atan2DivFastest(long y, long x) { +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(y >= 0 && x > 0 && x >= y); +#endif // Normalize input into [1.0, 2.0( range (convert to s2.30). const int ONE = (1 << 30); +#if !DISABLE_RUNTIME_VALIDATION const int HALF = (1 << 29); +#endif int offset = 31 - Nlz((ulong)x); int n = (int)(((offset >= 0) ? (x >> offset) : (x << -offset)) >> 2); int k = n - ONE; // Polynomial approximation. int oox = FixedUtil.RcpPoly4(k); +#if !DISABLE_RUNTIME_VALIDATION Debug.Assert(oox >= HALF && oox <= ONE); +#endif // Apply exponent and multiply. long yr = (offset >= 0) ? (y >> offset) : (y << -offset); @@ -1453,7 +1567,9 @@ public static long Atan2Fastest(long y, long x) if (y > 0) return PiHalf; if (y < 0) return -PiHalf; +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Atan2Fastest", "y, x", y, x); +#endif return 0; } @@ -1485,7 +1601,9 @@ public static long Asin(long x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Asin", "x", x); +#endif return 0; } @@ -1497,7 +1615,9 @@ public static long AsinFast(long x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.AsinFast", "x", x); +#endif return 0; } @@ -1509,7 +1629,9 @@ public static long AsinFastest(long x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.AsinFastest", "x", x); +#endif return 0; } @@ -1521,7 +1643,9 @@ public static long Acos(long x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.Acos", "x", x); +#endif return 0; } @@ -1533,7 +1657,9 @@ public static long AcosFast(long x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.AcosFast", "x", x); +#endif return 0; } @@ -1545,7 +1671,9 @@ public static long AcosFastest(long x) // Return 0 for invalid values if (x < -One || x > One) { +#if !DISABLE_RUNTIME_VALIDATION FixedUtil.InvalidArgument("Fixed64.AcosFastest", "x", x); +#endif return 0; } diff --git a/FixPointCS/FixedUtil.cs b/FixPointCS/FixedUtil.cs index 84da1e3..44107a3 100644 --- a/FixPointCS/FixedUtil.cs +++ b/FixPointCS/FixedUtil.cs @@ -22,6 +22,8 @@ // SOFTWARE. // +//#define DISABLE_RUNTIME_VALIDATION + // PREFIX #if CPP #elif JAVA @@ -98,6 +100,7 @@ public static void InvalidArgument(String funcName, String argName, long argValu // Backwards compatible way to use MethodImplOptions.AggressiveInlining public const MethodImplOptions AggressiveInlining = (MethodImplOptions)256; +#if !DISABLE_RUNTIME_VALIDATION private static Action InvalidArgumentHandler32 = (funcName, argName, argValue) => { }; private static Action InvalidArgumentHandler32_32 = (funcName, argName, argValue1, argValue2) => { }; private static Action InvalidArgumentHandler64 = (funcName, argName, argValue) => { }; @@ -153,6 +156,7 @@ public static void InvalidArgument(string funcName, string argNames, long argVal { InvalidArgumentHandler64_64.Invoke(funcName, argNames, argValue1, argValue2); } +#endif // !DISABLE_RUNTIME_VALIDATION #endif [MethodImpl(AggressiveInlining)]