diff --git a/Abacus.nuspec b/Abacus.nuspec index 2e8cd78..e303bb7 100644 --- a/Abacus.nuspec +++ b/Abacus.nuspec @@ -3,7 +3,7 @@ Abacus Abacus - 1.1.0 + 1.1.1 Ash Pook Ash Pook https://raw.githubusercontent.com/sungiant/abacus/master/LICENSE diff --git a/source/abacus/gen/main/Abacus.X.t4 b/source/abacus/gen/main/Abacus.X.t4 index 1e5bad7..f0547f1 100644 --- a/source/abacus/gen/main/Abacus.X.t4 +++ b/source/abacus/gen/main/Abacus.X.t4 @@ -4,7 +4,7 @@ // │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ // │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ // │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ // │ │ \\ // │ Fast, efficient, cross platform, cross precision, maths library. │ \\ // │ │ \\ @@ -23,7 +23,7 @@ // │ \________________________________________________________/ │ \\ // │ │ \\ // ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ // ├────────────────────────────────────────────────────────────────────────┤ \\ // │ Permission is hereby granted, free of charge, to any person obtaining │ \\ // │ a copy of this software and associated documentation files (the │ \\ diff --git a/source/abacus/gen/test/Abacus.X.Tests.t4 b/source/abacus/gen/test/Abacus.X.Tests.t4 index 1a4e11b..5926a3d 100644 --- a/source/abacus/gen/test/Abacus.X.Tests.t4 +++ b/source/abacus/gen/test/Abacus.X.Tests.t4 @@ -4,7 +4,7 @@ // │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ // │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ // │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ // │ │ \\ // │ Fast, efficient, cross platform, cross precision, maths library. │ \\ // │ │ \\ @@ -23,7 +23,7 @@ // │ \________________________________________________________/ │ \\ // │ │ \\ // ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ // ├────────────────────────────────────────────────────────────────────────┤ \\ // │ Permission is hereby granted, free of charge, to any person obtaining │ \\ // │ a copy of this software and associated documentation files (the │ \\ diff --git a/source/abacus/src/main/Abacus.Double.cs b/source/abacus/src/main/Abacus.Double.cs index 27e8d8f..ccaaa07 100644 --- a/source/abacus/src/main/Abacus.Double.cs +++ b/source/abacus/src/main/Abacus.Double.cs @@ -1,59 +1,59 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using MI = System.Runtime.CompilerServices.MethodImplAttribute; -using O = System.Runtime.CompilerServices.MethodImplOptions; - -namespace Abacus.DoublePrecision -{ +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using MI = System.Runtime.CompilerServices.MethodImplAttribute; +using O = System.Runtime.CompilerServices.MethodImplOptions; + +namespace Abacus.DoublePrecision +{ /// /// Double precision Quaternion. /// @@ -825,13 +825,9 @@ static Matrix44 () { // Angle of rotation, in radians. Angles are measured anti-clockwise when viewed from the rotation axis (positive side) toward the origin. [MI(O.AggressiveInlining)] public static void CreateFromYawPitchRoll (ref Double yaw, ref Double pitch, ref Double roll, out Matrix44 r) { - Double cy = Maths.Cos (yaw), sy = Maths.Sin (yaw); - Double cx = Maths.Cos (pitch), sx = Maths.Sin (pitch); - Double cz = Maths.Cos (roll), sz = Maths.Sin (roll); - r.R0C0 = cz*cy+sz*sx*sy; r.R0C1 = sz*cx; r.R0C2 = -cz*sy+sz*sx*cy; r.R0C3 = 0; - r.R1C0 = -sz*cy+cz*sx*sy; r.R1C1 = cz*cx; r.R1C2 = -cz*sy+sz*sx*cy; r.R1C3 = 0; - r.R2C0 = cx*sy; r.R2C1 = -sx; r.R2C2 = cx*cy; r.R2C3 = 0; - r.R3C0 = 0; r.R3C1 = 0; r.R3C2 = 0; r.R3C3 = 1; + Quaternion quaternion; + Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out quaternion); + CreateFromQuaternion(ref quaternion, out r); } // http://msdn.microsoft.com/en-us/library/bb205351(v=vs.85).aspx @@ -1735,66 +1731,66 @@ static Vector4 () { [MI(O.AggressiveInlining)] public static Double LengthSquared (Vector4 v) { Double r; LengthSquared (ref v, out r); return r; } } - /// - /// Provides maths functions with consistent function signatures across supported precisions. - /// - public static class Maths { - public static readonly Double Epsilon = (Double) 0.000001; - public static readonly Double E = 2.71828182845904523536028747135; - public static readonly Double Half = 0.5; - public static readonly Double Quarter = 0.25; - public static readonly Double Log10E = 0.43429448190325182765112891892; - public static readonly Double Log2E = 1.44269504088896340735992468100; - public static readonly Double Pi = 3.14159265358979323846264338328; - public static readonly Double HalfPi = 1.57079632679489661923132169164; - public static readonly Double QuarterPi = 0.78539816339744830961566084582; - public static readonly Double Root2 = 1.41421356237309504880168872421; - public static readonly Double Root3 = 1.73205080756887729352744634151; - public static readonly Double Tau = 6.28318530717958647692528676656; - public static readonly Double Deg2Rad = 0.01745329251994329576923690768; - public static readonly Double Rad2Deg = 57.29577951308232087679815481409; - public static readonly Double Zero = 0.0; - public static readonly Double One = 1.0; - - [MI(O.AggressiveInlining)] public static Double Sqrt (Double v) { return Math.Sqrt (v); } - [MI(O.AggressiveInlining)] public static Double Abs (Double v) { return Math.Abs (v); } - - [MI(O.AggressiveInlining)] public static Double Sin (Double v) { return Math.Sin (v); } - [MI(O.AggressiveInlining)] public static Double Cos (Double v) { return Math.Cos (v); } - [MI(O.AggressiveInlining)] public static Double Tan (Double v) { return Math.Tan (v); } - [MI(O.AggressiveInlining)] public static Double ArcCos (Double v) { return Math.Acos (v); } - [MI(O.AggressiveInlining)] public static Double ArcSin (Double v) { return Math.Asin (v); } - [MI(O.AggressiveInlining)] public static Double ArcTan (Double v) { return Math.Atan (v); } - [MI(O.AggressiveInlining)] public static Double ArcTan2 (Double y, Double x) { return Math.Atan2 (y, x); } - - - [MI(O.AggressiveInlining)] public static Double ToRadians (Double input) { return input * Deg2Rad; } - [MI(O.AggressiveInlining)] public static Double ToDegrees (Double input) { return input * Rad2Deg; } - [MI(O.AggressiveInlining)] public static Double FromFraction (Int32 numerator, Int32 denominator) { return (Double) numerator / (Double) denominator; } - [MI(O.AggressiveInlining)] public static Double FromFraction (Int64 numerator, Int64 denominator) { return (Double) numerator / (Double) denominator; } - - [MI(O.AggressiveInlining)] public static Double Min (Double a, Double b) { return a < b ? a : b; } - [MI(O.AggressiveInlining)] public static Double Max (Double a, Double b) { return a > b ? a : b; } - [MI(O.AggressiveInlining)] public static Double Clamp (Double value, Double min, Double max) { if (value < min) return min; else if (value > max) return max; else return value; } - [MI(O.AggressiveInlining)] public static Double Lerp (Double a, Double b, Double t) { return a + ((b - a) * t); } - - [MI(O.AggressiveInlining)] public static Double FromString (String str) { Double result = Zero; Double.TryParse (str, out result); return result; } - [MI(O.AggressiveInlining)] public static void FromString (String str, out Double value) { Double.TryParse (str, out value); } - - [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Double value) { return Abs(value) < Epsilon; } - [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Double a, Double b) { Double num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } - - [MI(O.AggressiveInlining)] public static Int32 Sign (Double value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } - [MI(O.AggressiveInlining)] public static Double CopySign (Double x, Double y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } - } - - - internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx - public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { - positions = positions & 0x1F; - uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); - uint wrapped = number >> (32 - positions); - return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); - } - } -} + /// + /// Provides maths functions with consistent function signatures across supported precisions. + /// + public static class Maths { + public static readonly Double Epsilon = (Double) 0.000001; + public static readonly Double E = 2.71828182845904523536028747135; + public static readonly Double Half = 0.5; + public static readonly Double Quarter = 0.25; + public static readonly Double Log10E = 0.43429448190325182765112891892; + public static readonly Double Log2E = 1.44269504088896340735992468100; + public static readonly Double Pi = 3.14159265358979323846264338328; + public static readonly Double HalfPi = 1.57079632679489661923132169164; + public static readonly Double QuarterPi = 0.78539816339744830961566084582; + public static readonly Double Root2 = 1.41421356237309504880168872421; + public static readonly Double Root3 = 1.73205080756887729352744634151; + public static readonly Double Tau = 6.28318530717958647692528676656; + public static readonly Double Deg2Rad = 0.01745329251994329576923690768; + public static readonly Double Rad2Deg = 57.29577951308232087679815481409; + public static readonly Double Zero = 0.0; + public static readonly Double One = 1.0; + + [MI(O.AggressiveInlining)] public static Double Sqrt (Double v) { return Math.Sqrt (v); } + [MI(O.AggressiveInlining)] public static Double Abs (Double v) { return Math.Abs (v); } + + [MI(O.AggressiveInlining)] public static Double Sin (Double v) { return Math.Sin (v); } + [MI(O.AggressiveInlining)] public static Double Cos (Double v) { return Math.Cos (v); } + [MI(O.AggressiveInlining)] public static Double Tan (Double v) { return Math.Tan (v); } + [MI(O.AggressiveInlining)] public static Double ArcCos (Double v) { return Math.Acos (v); } + [MI(O.AggressiveInlining)] public static Double ArcSin (Double v) { return Math.Asin (v); } + [MI(O.AggressiveInlining)] public static Double ArcTan (Double v) { return Math.Atan (v); } + [MI(O.AggressiveInlining)] public static Double ArcTan2 (Double y, Double x) { return Math.Atan2 (y, x); } + + + [MI(O.AggressiveInlining)] public static Double ToRadians (Double input) { return input * Deg2Rad; } + [MI(O.AggressiveInlining)] public static Double ToDegrees (Double input) { return input * Rad2Deg; } + [MI(O.AggressiveInlining)] public static Double FromFraction (Int32 numerator, Int32 denominator) { return (Double) numerator / (Double) denominator; } + [MI(O.AggressiveInlining)] public static Double FromFraction (Int64 numerator, Int64 denominator) { return (Double) numerator / (Double) denominator; } + + [MI(O.AggressiveInlining)] public static Double Min (Double a, Double b) { return a < b ? a : b; } + [MI(O.AggressiveInlining)] public static Double Max (Double a, Double b) { return a > b ? a : b; } + [MI(O.AggressiveInlining)] public static Double Clamp (Double value, Double min, Double max) { if (value < min) return min; else if (value > max) return max; else return value; } + [MI(O.AggressiveInlining)] public static Double Lerp (Double a, Double b, Double t) { return a + ((b - a) * t); } + + [MI(O.AggressiveInlining)] public static Double FromString (String str) { Double result = Zero; Double.TryParse (str, out result); return result; } + [MI(O.AggressiveInlining)] public static void FromString (String str, out Double value) { Double.TryParse (str, out value); } + + [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Double value) { return Abs(value) < Epsilon; } + [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Double a, Double b) { Double num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } + + [MI(O.AggressiveInlining)] public static Int32 Sign (Double value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } + [MI(O.AggressiveInlining)] public static Double CopySign (Double x, Double y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } + } + + + internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx + public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { + positions = positions & 0x1F; + uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); + uint wrapped = number >> (32 - positions); + return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); + } + } +} diff --git a/source/abacus/src/main/Abacus.Fixed32.cs b/source/abacus/src/main/Abacus.Fixed32.cs index c789656..a453c05 100644 --- a/source/abacus/src/main/Abacus.Fixed32.cs +++ b/source/abacus/src/main/Abacus.Fixed32.cs @@ -1,60 +1,60 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using MI = System.Runtime.CompilerServices.MethodImplAttribute; -using O = System.Runtime.CompilerServices.MethodImplOptions; -using System.Globalization; - -namespace Abacus.Fixed32Precision -{ +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using MI = System.Runtime.CompilerServices.MethodImplAttribute; +using O = System.Runtime.CompilerServices.MethodImplOptions; +using System.Globalization; + +namespace Abacus.Fixed32Precision +{ /// /// 32 bit signed Q16.16 number. /// @@ -289,9 +289,9 @@ public struct Fixed32 : IEquatable { } [MI(O.AggressiveInlining)] public static void Sin (ref Fixed32 f, out Fixed32 r) { - Fixed32 Tau = Fixed32.CreateFrom (6.28318530717958647692528676656); - Fixed32 Pi = Fixed32.CreateFrom (3.14159265358979323846264338328); - Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); + Fixed32 Tau = Fixed32.CreateFrom (6.28318530717958647692528676656); + Fixed32 Pi = Fixed32.CreateFrom (3.14159265358979323846264338328); + Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); // Based on: https://stackoverflow.com/questions/605124/fixed-point-math-in-c Fixed32 fx = f; @@ -325,7 +325,7 @@ public struct Fixed32 : IEquatable { } [MI(O.AggressiveInlining)] public static void Cos (ref Fixed32 f, out Fixed32 r) { - Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); + Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); Fixed32 fx = HalfPi - f; Sin (ref fx, out r); } @@ -369,7 +369,7 @@ public struct Fixed32 : IEquatable { // best accuracy for which falls within the range of -1 <= f <= 1, see: https://spin.atomicobject.com/2012/04/24/implementing-advanced-math-functions/ // Valid input for the ArcTan function falls within the range of -∞ < f < ∞, // trig identities are used to facilitate performing the approximation within the most accurate range: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions - Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); + Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); Fixed32 temp = f; Boolean use_negative_identity = temp < 0; if (use_negative_identity) temp = -temp; @@ -396,8 +396,8 @@ public struct Fixed32 : IEquatable { } [MI(O.AggressiveInlining)] public static void ArcTan2 (ref Fixed32 y, ref Fixed32 x, out Fixed32 r) { - Fixed32 Pi = Fixed32.CreateFrom (3.14159265358979323846264338328); - Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); + Fixed32 Pi = Fixed32.CreateFrom (3.14159265358979323846264338328); + Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); // From definition and computation section of: https://en.wikipedia.org/wiki/Atan2 if (x > 0) { r = y / x; @@ -438,7 +438,7 @@ public struct Fixed32 : IEquatable { r = (Int32) big; } [MI(O.AggressiveInlining)] static void SinLookup (ref Fixed32 rad, out Fixed32 r) { - Fixed32 Rad2Deg = Fixed32.CreateFrom (57.29577951308232087679815481409); + Fixed32 Rad2Deg = Fixed32.CreateFrom (57.29577951308232087679815481409); Fixed32 deg = rad * Rad2Deg; Int32 p = (Int32) deg.ToInt32 (); @@ -457,20 +457,20 @@ public struct Fixed32 : IEquatable { r = low + q * (high - low); } - static readonly Int32[] sinLUT = { - 0x0, - 0x478, 0x8EF, 0xD66, 0x11DC, 0x1650, 0x1AC2, 0x1F33, 0x23A1, 0x280C, - 0x2C74, 0x30D9, 0x353A, 0x3996, 0x3DEF, 0x4242, 0x4690, 0x4AD9, 0x4F1C, - 0x5358, 0x578F, 0x5BBE, 0x5FE6, 0x6407, 0x6820, 0x6C31, 0x7039, 0x7439, - 0x782F, 0x7C1C, 0x8000, 0x83DA, 0x87A9, 0x8B6D, 0x8F27, 0x92D6, 0x9679, - 0x9A11, 0x9D9C, 0xA11B, 0xA48E, 0xA7F3, 0xAB4C, 0xAE97, 0xB1D5, 0xB505, - 0xB827, 0xBB3A, 0xBE3F, 0xC135, 0xC41B, 0xC6F3, 0xC9BB, 0xCC73, 0xCF1C, - 0xD1B4, 0xD43C, 0xD6B3, 0xD91A, 0xDB6F, 0xDDB4, 0xDFE7, 0xE209, 0xE419, - 0xE617, 0xE804, 0xE9DE, 0xEBA6, 0xED5C, 0xEEFF, 0xF090, 0xF20E, 0xF378, - 0xF4D0, 0xF615, 0xF747, 0xF865, 0xF970, 0xFA68, 0xFB4C, 0xFC1C, 0xFCD9, - 0xFD82, 0xFE18, 0xFE99, 0xFF07, 0xFF60, 0xFFA6, 0xFFD8, 0xFFF6, 0x10000, - }; - + static readonly Int32[] sinLUT = { + 0x0, + 0x478, 0x8EF, 0xD66, 0x11DC, 0x1650, 0x1AC2, 0x1F33, 0x23A1, 0x280C, + 0x2C74, 0x30D9, 0x353A, 0x3996, 0x3DEF, 0x4242, 0x4690, 0x4AD9, 0x4F1C, + 0x5358, 0x578F, 0x5BBE, 0x5FE6, 0x6407, 0x6820, 0x6C31, 0x7039, 0x7439, + 0x782F, 0x7C1C, 0x8000, 0x83DA, 0x87A9, 0x8B6D, 0x8F27, 0x92D6, 0x9679, + 0x9A11, 0x9D9C, 0xA11B, 0xA48E, 0xA7F3, 0xAB4C, 0xAE97, 0xB1D5, 0xB505, + 0xB827, 0xBB3A, 0xBE3F, 0xC135, 0xC41B, 0xC6F3, 0xC9BB, 0xCC73, 0xCF1C, + 0xD1B4, 0xD43C, 0xD6B3, 0xD91A, 0xDB6F, 0xDDB4, 0xDFE7, 0xE209, 0xE419, + 0xE617, 0xE804, 0xE9DE, 0xEBA6, 0xED5C, 0xEEFF, 0xF090, 0xF20E, 0xF378, + 0xF4D0, 0xF615, 0xF747, 0xF865, 0xF970, 0xFA68, 0xFB4C, 0xFC1C, 0xFCD9, + 0xFD82, 0xFE18, 0xFE99, 0xFF07, 0xFF60, 0xFFA6, 0xFFD8, 0xFFF6, 0x10000, + }; + // Function Variants //-----------------------------------------------// @@ -1295,13 +1295,9 @@ static Matrix44 () { // Angle of rotation, in radians. Angles are measured anti-clockwise when viewed from the rotation axis (positive side) toward the origin. [MI(O.AggressiveInlining)] public static void CreateFromYawPitchRoll (ref Fixed32 yaw, ref Fixed32 pitch, ref Fixed32 roll, out Matrix44 r) { - Fixed32 cy = Maths.Cos (yaw), sy = Maths.Sin (yaw); - Fixed32 cx = Maths.Cos (pitch), sx = Maths.Sin (pitch); - Fixed32 cz = Maths.Cos (roll), sz = Maths.Sin (roll); - r.R0C0 = cz*cy+sz*sx*sy; r.R0C1 = sz*cx; r.R0C2 = -cz*sy+sz*sx*cy; r.R0C3 = 0; - r.R1C0 = -sz*cy+cz*sx*sy; r.R1C1 = cz*cx; r.R1C2 = -cz*sy+sz*sx*cy; r.R1C3 = 0; - r.R2C0 = cx*sy; r.R2C1 = -sx; r.R2C2 = cx*cy; r.R2C3 = 0; - r.R3C0 = 0; r.R3C1 = 0; r.R3C2 = 0; r.R3C3 = 1; + Quaternion quaternion; + Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out quaternion); + CreateFromQuaternion(ref quaternion, out r); } // http://msdn.microsoft.com/en-us/library/bb205351(v=vs.85).aspx @@ -2205,66 +2201,66 @@ static Vector4 () { [MI(O.AggressiveInlining)] public static Fixed32 LengthSquared (Vector4 v) { Fixed32 r; LengthSquared (ref v, out r); return r; } } - /// - /// Provides maths functions with consistent function signatures across supported precisions. - /// - public static class Maths { - public static readonly Fixed32 Epsilon = (Fixed32) 0.000001; - public static readonly Fixed32 E = Fixed32.CreateFrom (2.71828182845904523536028747135); - public static readonly Fixed32 Half = Fixed32.CreateFrom (0.5); - public static readonly Fixed32 Quarter = Fixed32.CreateFrom (0.25); - public static readonly Fixed32 Log10E = Fixed32.CreateFrom (0.43429448190325182765112891892); - public static readonly Fixed32 Log2E = Fixed32.CreateFrom (1.44269504088896340735992468100); - public static readonly Fixed32 Pi = Fixed32.CreateFrom (3.14159265358979323846264338328); - public static readonly Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); - public static readonly Fixed32 QuarterPi = Fixed32.CreateFrom (0.78539816339744830961566084582); - public static readonly Fixed32 Root2 = Fixed32.CreateFrom (1.41421356237309504880168872421); - public static readonly Fixed32 Root3 = Fixed32.CreateFrom (1.73205080756887729352744634151); - public static readonly Fixed32 Tau = Fixed32.CreateFrom (6.28318530717958647692528676656); - public static readonly Fixed32 Deg2Rad = Fixed32.CreateFrom (0.01745329251994329576923690768); - public static readonly Fixed32 Rad2Deg = Fixed32.CreateFrom (57.29577951308232087679815481409); - public static readonly Fixed32 Zero = Fixed32.CreateFrom (0.0); - public static readonly Fixed32 One = Fixed32.CreateFrom (1.0); - - [MI(O.AggressiveInlining)] public static Fixed32 Sqrt (Fixed32 v) { return Fixed32.Sqrt (v); } - [MI(O.AggressiveInlining)] public static Fixed32 Abs (Fixed32 v) { return Fixed32.Abs (v); } - - [MI(O.AggressiveInlining)] public static Fixed32 Sin (Fixed32 v) { return Fixed32.Sin (v); } - [MI(O.AggressiveInlining)] public static Fixed32 Cos (Fixed32 v) { return Fixed32.Cos (v); } - [MI(O.AggressiveInlining)] public static Fixed32 Tan (Fixed32 v) { return Fixed32.Tan (v); } - [MI(O.AggressiveInlining)] public static Fixed32 ArcCos (Fixed32 v) { return Fixed32.ArcCos (v); } - [MI(O.AggressiveInlining)] public static Fixed32 ArcSin (Fixed32 v) { return Fixed32.ArcSin (v); } - [MI(O.AggressiveInlining)] public static Fixed32 ArcTan (Fixed32 v) { return Fixed32.ArcTan (v); } - [MI(O.AggressiveInlining)] public static Fixed32 ArcTan2 (Fixed32 y, Fixed32 x) { return Fixed32.ArcTan2 (y, x); } - - - [MI(O.AggressiveInlining)] public static Fixed32 ToRadians (Fixed32 input) { return input * Deg2Rad; } - [MI(O.AggressiveInlining)] public static Fixed32 ToDegrees (Fixed32 input) { return input * Rad2Deg; } - [MI(O.AggressiveInlining)] public static Fixed32 FromFraction (Int32 numerator, Int32 denominator) { return (Fixed32) numerator / (Fixed32) denominator; } - [MI(O.AggressiveInlining)] public static Fixed32 FromFraction (Int64 numerator, Int64 denominator) { return (Fixed32) numerator / (Fixed32) denominator; } - - [MI(O.AggressiveInlining)] public static Fixed32 Min (Fixed32 a, Fixed32 b) { return a < b ? a : b; } - [MI(O.AggressiveInlining)] public static Fixed32 Max (Fixed32 a, Fixed32 b) { return a > b ? a : b; } - [MI(O.AggressiveInlining)] public static Fixed32 Clamp (Fixed32 value, Fixed32 min, Fixed32 max) { if (value < min) return min; else if (value > max) return max; else return value; } - [MI(O.AggressiveInlining)] public static Fixed32 Lerp (Fixed32 a, Fixed32 b, Fixed32 t) { return a + ((b - a) * t); } - - [MI(O.AggressiveInlining)] public static Fixed32 FromString (String str) { Fixed32 result = Zero; Fixed32.TryParse (str, out result); return result; } - [MI(O.AggressiveInlining)] public static void FromString (String str, out Fixed32 value) { Fixed32.TryParse (str, out value); } - - [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Fixed32 value) { return Abs(value) < Epsilon; } - [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Fixed32 a, Fixed32 b) { Fixed32 num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } - - [MI(O.AggressiveInlining)] public static Int32 Sign (Fixed32 value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } - [MI(O.AggressiveInlining)] public static Fixed32 CopySign (Fixed32 x, Fixed32 y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } - } - - - internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx - public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { - positions = positions & 0x1F; - uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); - uint wrapped = number >> (32 - positions); - return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); - } - } -} + /// + /// Provides maths functions with consistent function signatures across supported precisions. + /// + public static class Maths { + public static readonly Fixed32 Epsilon = (Fixed32) 0.000001; + public static readonly Fixed32 E = Fixed32.CreateFrom (2.71828182845904523536028747135); + public static readonly Fixed32 Half = Fixed32.CreateFrom (0.5); + public static readonly Fixed32 Quarter = Fixed32.CreateFrom (0.25); + public static readonly Fixed32 Log10E = Fixed32.CreateFrom (0.43429448190325182765112891892); + public static readonly Fixed32 Log2E = Fixed32.CreateFrom (1.44269504088896340735992468100); + public static readonly Fixed32 Pi = Fixed32.CreateFrom (3.14159265358979323846264338328); + public static readonly Fixed32 HalfPi = Fixed32.CreateFrom (1.57079632679489661923132169164); + public static readonly Fixed32 QuarterPi = Fixed32.CreateFrom (0.78539816339744830961566084582); + public static readonly Fixed32 Root2 = Fixed32.CreateFrom (1.41421356237309504880168872421); + public static readonly Fixed32 Root3 = Fixed32.CreateFrom (1.73205080756887729352744634151); + public static readonly Fixed32 Tau = Fixed32.CreateFrom (6.28318530717958647692528676656); + public static readonly Fixed32 Deg2Rad = Fixed32.CreateFrom (0.01745329251994329576923690768); + public static readonly Fixed32 Rad2Deg = Fixed32.CreateFrom (57.29577951308232087679815481409); + public static readonly Fixed32 Zero = Fixed32.CreateFrom (0.0); + public static readonly Fixed32 One = Fixed32.CreateFrom (1.0); + + [MI(O.AggressiveInlining)] public static Fixed32 Sqrt (Fixed32 v) { return Fixed32.Sqrt (v); } + [MI(O.AggressiveInlining)] public static Fixed32 Abs (Fixed32 v) { return Fixed32.Abs (v); } + + [MI(O.AggressiveInlining)] public static Fixed32 Sin (Fixed32 v) { return Fixed32.Sin (v); } + [MI(O.AggressiveInlining)] public static Fixed32 Cos (Fixed32 v) { return Fixed32.Cos (v); } + [MI(O.AggressiveInlining)] public static Fixed32 Tan (Fixed32 v) { return Fixed32.Tan (v); } + [MI(O.AggressiveInlining)] public static Fixed32 ArcCos (Fixed32 v) { return Fixed32.ArcCos (v); } + [MI(O.AggressiveInlining)] public static Fixed32 ArcSin (Fixed32 v) { return Fixed32.ArcSin (v); } + [MI(O.AggressiveInlining)] public static Fixed32 ArcTan (Fixed32 v) { return Fixed32.ArcTan (v); } + [MI(O.AggressiveInlining)] public static Fixed32 ArcTan2 (Fixed32 y, Fixed32 x) { return Fixed32.ArcTan2 (y, x); } + + + [MI(O.AggressiveInlining)] public static Fixed32 ToRadians (Fixed32 input) { return input * Deg2Rad; } + [MI(O.AggressiveInlining)] public static Fixed32 ToDegrees (Fixed32 input) { return input * Rad2Deg; } + [MI(O.AggressiveInlining)] public static Fixed32 FromFraction (Int32 numerator, Int32 denominator) { return (Fixed32) numerator / (Fixed32) denominator; } + [MI(O.AggressiveInlining)] public static Fixed32 FromFraction (Int64 numerator, Int64 denominator) { return (Fixed32) numerator / (Fixed32) denominator; } + + [MI(O.AggressiveInlining)] public static Fixed32 Min (Fixed32 a, Fixed32 b) { return a < b ? a : b; } + [MI(O.AggressiveInlining)] public static Fixed32 Max (Fixed32 a, Fixed32 b) { return a > b ? a : b; } + [MI(O.AggressiveInlining)] public static Fixed32 Clamp (Fixed32 value, Fixed32 min, Fixed32 max) { if (value < min) return min; else if (value > max) return max; else return value; } + [MI(O.AggressiveInlining)] public static Fixed32 Lerp (Fixed32 a, Fixed32 b, Fixed32 t) { return a + ((b - a) * t); } + + [MI(O.AggressiveInlining)] public static Fixed32 FromString (String str) { Fixed32 result = Zero; Fixed32.TryParse (str, out result); return result; } + [MI(O.AggressiveInlining)] public static void FromString (String str, out Fixed32 value) { Fixed32.TryParse (str, out value); } + + [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Fixed32 value) { return Abs(value) < Epsilon; } + [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Fixed32 a, Fixed32 b) { Fixed32 num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } + + [MI(O.AggressiveInlining)] public static Int32 Sign (Fixed32 value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } + [MI(O.AggressiveInlining)] public static Fixed32 CopySign (Fixed32 x, Fixed32 y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } + } + + + internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx + public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { + positions = positions & 0x1F; + uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); + uint wrapped = number >> (32 - positions); + return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); + } + } +} diff --git a/source/abacus/src/main/Abacus.Fixed64.cs b/source/abacus/src/main/Abacus.Fixed64.cs index eb68a0e..eb2d92d 100644 --- a/source/abacus/src/main/Abacus.Fixed64.cs +++ b/source/abacus/src/main/Abacus.Fixed64.cs @@ -1,61 +1,61 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using MI = System.Runtime.CompilerServices.MethodImplAttribute; -using O = System.Runtime.CompilerServices.MethodImplOptions; -using System.Globalization; -using System.Numerics; - -namespace Abacus.Fixed64Precision -{ +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using MI = System.Runtime.CompilerServices.MethodImplAttribute; +using O = System.Runtime.CompilerServices.MethodImplOptions; +using System.Globalization; +using System.Numerics; + +namespace Abacus.Fixed64Precision +{ /// /// 64 bit signed Q40.24 number. /// @@ -290,9 +290,9 @@ public struct Fixed64 : IEquatable { } [MI(O.AggressiveInlining)] public static void Sin (ref Fixed64 f, out Fixed64 r) { - Fixed64 Tau = Fixed64.CreateFrom (6.28318530717958647692528676656); - Fixed64 Pi = Fixed64.CreateFrom (3.14159265358979323846264338328); - Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); + Fixed64 Tau = Fixed64.CreateFrom (6.28318530717958647692528676656); + Fixed64 Pi = Fixed64.CreateFrom (3.14159265358979323846264338328); + Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); // Based on: https://stackoverflow.com/questions/605124/fixed-point-math-in-c Fixed64 fx = f; @@ -326,7 +326,7 @@ public struct Fixed64 : IEquatable { } [MI(O.AggressiveInlining)] public static void Cos (ref Fixed64 f, out Fixed64 r) { - Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); + Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); Fixed64 fx = HalfPi - f; Sin (ref fx, out r); } @@ -370,7 +370,7 @@ public struct Fixed64 : IEquatable { // best accuracy for which falls within the range of -1 <= f <= 1, see: https://spin.atomicobject.com/2012/04/24/implementing-advanced-math-functions/ // Valid input for the ArcTan function falls within the range of -∞ < f < ∞, // trig identities are used to facilitate performing the approximation within the most accurate range: https://en.wikipedia.org/wiki/Inverse_trigonometric_functions - Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); + Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); Fixed64 temp = f; Boolean use_negative_identity = temp < 0; if (use_negative_identity) temp = -temp; @@ -397,8 +397,8 @@ public struct Fixed64 : IEquatable { } [MI(O.AggressiveInlining)] public static void ArcTan2 (ref Fixed64 y, ref Fixed64 x, out Fixed64 r) { - Fixed64 Pi = Fixed64.CreateFrom (3.14159265358979323846264338328); - Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); + Fixed64 Pi = Fixed64.CreateFrom (3.14159265358979323846264338328); + Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); // From definition and computation section of: https://en.wikipedia.org/wiki/Atan2 if (x > 0) { r = y / x; @@ -439,7 +439,7 @@ public struct Fixed64 : IEquatable { r = (Int64) big; } [MI(O.AggressiveInlining)] static void SinLookup (ref Fixed64 rad, out Fixed64 r) { - Fixed64 Rad2Deg = Fixed64.CreateFrom (57.29577951308232087679815481409); + Fixed64 Rad2Deg = Fixed64.CreateFrom (57.29577951308232087679815481409); Fixed64 deg = rad * Rad2Deg; Int32 p = (Int32) deg.ToInt32 (); @@ -458,20 +458,20 @@ public struct Fixed64 : IEquatable { r = low + q * (high - low); } - static readonly Int64[] sinLUT = { - 0x0, - 0x477C3, 0x8EF2C, 0xD65E4, 0x11DB8F, 0x164FD7, 0x1AC261, 0x1F32D4, 0x23A0D9, 0x280C17, - 0x2C7435, 0x30D8DC, 0x3539B3, 0x399664, 0x3DEE98, 0x4241F7, 0x46902B, 0x4AD8DF, 0x4F1BBD, - 0x53586F, 0x578EA2, 0x5BBE00, 0x5FE638, 0x6406F5, 0x681FE5, 0x6C30B6, 0x703917, 0x7438B9, - 0x782F4A, 0x7C1C7C, 0x800000, 0x83D989, 0x87A8CA, 0x8B6D77, 0x8F2744, 0x92D5E8, 0x967918, - 0x9A108D, 0x9D9BFE, 0xA11B24, 0xA48DBB, 0xA7F37C, 0xAB4C25, 0xAE9772, 0xB1D522, 0xB504F3, - 0xB826A7, 0xBB39FF, 0xBE3EBD, 0xC134A6, 0xC41B7D, 0xC6F30A, 0xC9BB13, 0xCC7360, 0xCF1BBD, - 0xD1B3F3, 0xD43BCE, 0xD6B31D, 0xD919AE, 0xDB6F51, 0xDDB3D7, 0xDFE714, 0xE208DA, 0xE41901, - 0xE6175E, 0xE803CA, 0xE9DE1D, 0xEBA635, 0xED5BEC, 0xEEFF20, 0xF08FB2, 0xF20D81, 0xF37871, - 0xF4D063, 0xF6153F, 0xF746EA, 0xF8654D, 0xF97051, 0xFA67E2, 0xFB4BEB, 0xFC1C5C, 0xFCD925, - 0xFD8235, 0xFE1781, 0xFE98FD, 0xFF069E, 0xFF605C, 0xFFA62F, 0xFFD814, 0xFFF605, 0x1000000, - }; - + static readonly Int64[] sinLUT = { + 0x0, + 0x477C3, 0x8EF2C, 0xD65E4, 0x11DB8F, 0x164FD7, 0x1AC261, 0x1F32D4, 0x23A0D9, 0x280C17, + 0x2C7435, 0x30D8DC, 0x3539B3, 0x399664, 0x3DEE98, 0x4241F7, 0x46902B, 0x4AD8DF, 0x4F1BBD, + 0x53586F, 0x578EA2, 0x5BBE00, 0x5FE638, 0x6406F5, 0x681FE5, 0x6C30B6, 0x703917, 0x7438B9, + 0x782F4A, 0x7C1C7C, 0x800000, 0x83D989, 0x87A8CA, 0x8B6D77, 0x8F2744, 0x92D5E8, 0x967918, + 0x9A108D, 0x9D9BFE, 0xA11B24, 0xA48DBB, 0xA7F37C, 0xAB4C25, 0xAE9772, 0xB1D522, 0xB504F3, + 0xB826A7, 0xBB39FF, 0xBE3EBD, 0xC134A6, 0xC41B7D, 0xC6F30A, 0xC9BB13, 0xCC7360, 0xCF1BBD, + 0xD1B3F3, 0xD43BCE, 0xD6B31D, 0xD919AE, 0xDB6F51, 0xDDB3D7, 0xDFE714, 0xE208DA, 0xE41901, + 0xE6175E, 0xE803CA, 0xE9DE1D, 0xEBA635, 0xED5BEC, 0xEEFF20, 0xF08FB2, 0xF20D81, 0xF37871, + 0xF4D063, 0xF6153F, 0xF746EA, 0xF8654D, 0xF97051, 0xFA67E2, 0xFB4BEB, 0xFC1C5C, 0xFCD925, + 0xFD8235, 0xFE1781, 0xFE98FD, 0xFF069E, 0xFF605C, 0xFFA62F, 0xFFD814, 0xFFF605, 0x1000000, + }; + // Function Variants //-----------------------------------------------// @@ -1296,13 +1296,9 @@ static Matrix44 () { // Angle of rotation, in radians. Angles are measured anti-clockwise when viewed from the rotation axis (positive side) toward the origin. [MI(O.AggressiveInlining)] public static void CreateFromYawPitchRoll (ref Fixed64 yaw, ref Fixed64 pitch, ref Fixed64 roll, out Matrix44 r) { - Fixed64 cy = Maths.Cos (yaw), sy = Maths.Sin (yaw); - Fixed64 cx = Maths.Cos (pitch), sx = Maths.Sin (pitch); - Fixed64 cz = Maths.Cos (roll), sz = Maths.Sin (roll); - r.R0C0 = cz*cy+sz*sx*sy; r.R0C1 = sz*cx; r.R0C2 = -cz*sy+sz*sx*cy; r.R0C3 = 0; - r.R1C0 = -sz*cy+cz*sx*sy; r.R1C1 = cz*cx; r.R1C2 = -cz*sy+sz*sx*cy; r.R1C3 = 0; - r.R2C0 = cx*sy; r.R2C1 = -sx; r.R2C2 = cx*cy; r.R2C3 = 0; - r.R3C0 = 0; r.R3C1 = 0; r.R3C2 = 0; r.R3C3 = 1; + Quaternion quaternion; + Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out quaternion); + CreateFromQuaternion(ref quaternion, out r); } // http://msdn.microsoft.com/en-us/library/bb205351(v=vs.85).aspx @@ -2206,66 +2202,66 @@ static Vector4 () { [MI(O.AggressiveInlining)] public static Fixed64 LengthSquared (Vector4 v) { Fixed64 r; LengthSquared (ref v, out r); return r; } } - /// - /// Provides maths functions with consistent function signatures across supported precisions. - /// - public static class Maths { - public static readonly Fixed64 Epsilon = (Fixed64) 0.000001; - public static readonly Fixed64 E = Fixed64.CreateFrom (2.71828182845904523536028747135); - public static readonly Fixed64 Half = Fixed64.CreateFrom (0.5); - public static readonly Fixed64 Quarter = Fixed64.CreateFrom (0.25); - public static readonly Fixed64 Log10E = Fixed64.CreateFrom (0.43429448190325182765112891892); - public static readonly Fixed64 Log2E = Fixed64.CreateFrom (1.44269504088896340735992468100); - public static readonly Fixed64 Pi = Fixed64.CreateFrom (3.14159265358979323846264338328); - public static readonly Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); - public static readonly Fixed64 QuarterPi = Fixed64.CreateFrom (0.78539816339744830961566084582); - public static readonly Fixed64 Root2 = Fixed64.CreateFrom (1.41421356237309504880168872421); - public static readonly Fixed64 Root3 = Fixed64.CreateFrom (1.73205080756887729352744634151); - public static readonly Fixed64 Tau = Fixed64.CreateFrom (6.28318530717958647692528676656); - public static readonly Fixed64 Deg2Rad = Fixed64.CreateFrom (0.01745329251994329576923690768); - public static readonly Fixed64 Rad2Deg = Fixed64.CreateFrom (57.29577951308232087679815481409); - public static readonly Fixed64 Zero = Fixed64.CreateFrom (0.0); - public static readonly Fixed64 One = Fixed64.CreateFrom (1.0); - - [MI(O.AggressiveInlining)] public static Fixed64 Sqrt (Fixed64 v) { return Fixed64.Sqrt (v); } - [MI(O.AggressiveInlining)] public static Fixed64 Abs (Fixed64 v) { return Fixed64.Abs (v); } - - [MI(O.AggressiveInlining)] public static Fixed64 Sin (Fixed64 v) { return Fixed64.Sin (v); } - [MI(O.AggressiveInlining)] public static Fixed64 Cos (Fixed64 v) { return Fixed64.Cos (v); } - [MI(O.AggressiveInlining)] public static Fixed64 Tan (Fixed64 v) { return Fixed64.Tan (v); } - [MI(O.AggressiveInlining)] public static Fixed64 ArcCos (Fixed64 v) { return Fixed64.ArcCos (v); } - [MI(O.AggressiveInlining)] public static Fixed64 ArcSin (Fixed64 v) { return Fixed64.ArcSin (v); } - [MI(O.AggressiveInlining)] public static Fixed64 ArcTan (Fixed64 v) { return Fixed64.ArcTan (v); } - [MI(O.AggressiveInlining)] public static Fixed64 ArcTan2 (Fixed64 y, Fixed64 x) { return Fixed64.ArcTan2 (y, x); } - - - [MI(O.AggressiveInlining)] public static Fixed64 ToRadians (Fixed64 input) { return input * Deg2Rad; } - [MI(O.AggressiveInlining)] public static Fixed64 ToDegrees (Fixed64 input) { return input * Rad2Deg; } - [MI(O.AggressiveInlining)] public static Fixed64 FromFraction (Int32 numerator, Int32 denominator) { return (Fixed64) numerator / (Fixed64) denominator; } - [MI(O.AggressiveInlining)] public static Fixed64 FromFraction (Int64 numerator, Int64 denominator) { return (Fixed64) numerator / (Fixed64) denominator; } - - [MI(O.AggressiveInlining)] public static Fixed64 Min (Fixed64 a, Fixed64 b) { return a < b ? a : b; } - [MI(O.AggressiveInlining)] public static Fixed64 Max (Fixed64 a, Fixed64 b) { return a > b ? a : b; } - [MI(O.AggressiveInlining)] public static Fixed64 Clamp (Fixed64 value, Fixed64 min, Fixed64 max) { if (value < min) return min; else if (value > max) return max; else return value; } - [MI(O.AggressiveInlining)] public static Fixed64 Lerp (Fixed64 a, Fixed64 b, Fixed64 t) { return a + ((b - a) * t); } - - [MI(O.AggressiveInlining)] public static Fixed64 FromString (String str) { Fixed64 result = Zero; Fixed64.TryParse (str, out result); return result; } - [MI(O.AggressiveInlining)] public static void FromString (String str, out Fixed64 value) { Fixed64.TryParse (str, out value); } - - [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Fixed64 value) { return Abs(value) < Epsilon; } - [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Fixed64 a, Fixed64 b) { Fixed64 num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } - - [MI(O.AggressiveInlining)] public static Int32 Sign (Fixed64 value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } - [MI(O.AggressiveInlining)] public static Fixed64 CopySign (Fixed64 x, Fixed64 y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } - } - - - internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx - public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { - positions = positions & 0x1F; - uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); - uint wrapped = number >> (32 - positions); - return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); - } - } -} + /// + /// Provides maths functions with consistent function signatures across supported precisions. + /// + public static class Maths { + public static readonly Fixed64 Epsilon = (Fixed64) 0.000001; + public static readonly Fixed64 E = Fixed64.CreateFrom (2.71828182845904523536028747135); + public static readonly Fixed64 Half = Fixed64.CreateFrom (0.5); + public static readonly Fixed64 Quarter = Fixed64.CreateFrom (0.25); + public static readonly Fixed64 Log10E = Fixed64.CreateFrom (0.43429448190325182765112891892); + public static readonly Fixed64 Log2E = Fixed64.CreateFrom (1.44269504088896340735992468100); + public static readonly Fixed64 Pi = Fixed64.CreateFrom (3.14159265358979323846264338328); + public static readonly Fixed64 HalfPi = Fixed64.CreateFrom (1.57079632679489661923132169164); + public static readonly Fixed64 QuarterPi = Fixed64.CreateFrom (0.78539816339744830961566084582); + public static readonly Fixed64 Root2 = Fixed64.CreateFrom (1.41421356237309504880168872421); + public static readonly Fixed64 Root3 = Fixed64.CreateFrom (1.73205080756887729352744634151); + public static readonly Fixed64 Tau = Fixed64.CreateFrom (6.28318530717958647692528676656); + public static readonly Fixed64 Deg2Rad = Fixed64.CreateFrom (0.01745329251994329576923690768); + public static readonly Fixed64 Rad2Deg = Fixed64.CreateFrom (57.29577951308232087679815481409); + public static readonly Fixed64 Zero = Fixed64.CreateFrom (0.0); + public static readonly Fixed64 One = Fixed64.CreateFrom (1.0); + + [MI(O.AggressiveInlining)] public static Fixed64 Sqrt (Fixed64 v) { return Fixed64.Sqrt (v); } + [MI(O.AggressiveInlining)] public static Fixed64 Abs (Fixed64 v) { return Fixed64.Abs (v); } + + [MI(O.AggressiveInlining)] public static Fixed64 Sin (Fixed64 v) { return Fixed64.Sin (v); } + [MI(O.AggressiveInlining)] public static Fixed64 Cos (Fixed64 v) { return Fixed64.Cos (v); } + [MI(O.AggressiveInlining)] public static Fixed64 Tan (Fixed64 v) { return Fixed64.Tan (v); } + [MI(O.AggressiveInlining)] public static Fixed64 ArcCos (Fixed64 v) { return Fixed64.ArcCos (v); } + [MI(O.AggressiveInlining)] public static Fixed64 ArcSin (Fixed64 v) { return Fixed64.ArcSin (v); } + [MI(O.AggressiveInlining)] public static Fixed64 ArcTan (Fixed64 v) { return Fixed64.ArcTan (v); } + [MI(O.AggressiveInlining)] public static Fixed64 ArcTan2 (Fixed64 y, Fixed64 x) { return Fixed64.ArcTan2 (y, x); } + + + [MI(O.AggressiveInlining)] public static Fixed64 ToRadians (Fixed64 input) { return input * Deg2Rad; } + [MI(O.AggressiveInlining)] public static Fixed64 ToDegrees (Fixed64 input) { return input * Rad2Deg; } + [MI(O.AggressiveInlining)] public static Fixed64 FromFraction (Int32 numerator, Int32 denominator) { return (Fixed64) numerator / (Fixed64) denominator; } + [MI(O.AggressiveInlining)] public static Fixed64 FromFraction (Int64 numerator, Int64 denominator) { return (Fixed64) numerator / (Fixed64) denominator; } + + [MI(O.AggressiveInlining)] public static Fixed64 Min (Fixed64 a, Fixed64 b) { return a < b ? a : b; } + [MI(O.AggressiveInlining)] public static Fixed64 Max (Fixed64 a, Fixed64 b) { return a > b ? a : b; } + [MI(O.AggressiveInlining)] public static Fixed64 Clamp (Fixed64 value, Fixed64 min, Fixed64 max) { if (value < min) return min; else if (value > max) return max; else return value; } + [MI(O.AggressiveInlining)] public static Fixed64 Lerp (Fixed64 a, Fixed64 b, Fixed64 t) { return a + ((b - a) * t); } + + [MI(O.AggressiveInlining)] public static Fixed64 FromString (String str) { Fixed64 result = Zero; Fixed64.TryParse (str, out result); return result; } + [MI(O.AggressiveInlining)] public static void FromString (String str, out Fixed64 value) { Fixed64.TryParse (str, out value); } + + [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Fixed64 value) { return Abs(value) < Epsilon; } + [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Fixed64 a, Fixed64 b) { Fixed64 num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } + + [MI(O.AggressiveInlining)] public static Int32 Sign (Fixed64 value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } + [MI(O.AggressiveInlining)] public static Fixed64 CopySign (Fixed64 x, Fixed64 y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } + } + + + internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx + public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { + positions = positions & 0x1F; + uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); + uint wrapped = number >> (32 - positions); + return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); + } + } +} diff --git a/source/abacus/src/main/Abacus.Single.cs b/source/abacus/src/main/Abacus.Single.cs index 895ae88..8642afe 100644 --- a/source/abacus/src/main/Abacus.Single.cs +++ b/source/abacus/src/main/Abacus.Single.cs @@ -1,59 +1,59 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.CompilerServices; -using MI = System.Runtime.CompilerServices.MethodImplAttribute; -using O = System.Runtime.CompilerServices.MethodImplOptions; - -namespace Abacus.SinglePrecision -{ +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using MI = System.Runtime.CompilerServices.MethodImplAttribute; +using O = System.Runtime.CompilerServices.MethodImplOptions; + +namespace Abacus.SinglePrecision +{ /// /// Single precision Quaternion. /// @@ -825,13 +825,9 @@ static Matrix44 () { // Angle of rotation, in radians. Angles are measured anti-clockwise when viewed from the rotation axis (positive side) toward the origin. [MI(O.AggressiveInlining)] public static void CreateFromYawPitchRoll (ref Single yaw, ref Single pitch, ref Single roll, out Matrix44 r) { - Single cy = Maths.Cos (yaw), sy = Maths.Sin (yaw); - Single cx = Maths.Cos (pitch), sx = Maths.Sin (pitch); - Single cz = Maths.Cos (roll), sz = Maths.Sin (roll); - r.R0C0 = cz*cy+sz*sx*sy; r.R0C1 = sz*cx; r.R0C2 = -cz*sy+sz*sx*cy; r.R0C3 = 0; - r.R1C0 = -sz*cy+cz*sx*sy; r.R1C1 = cz*cx; r.R1C2 = -cz*sy+sz*sx*cy; r.R1C3 = 0; - r.R2C0 = cx*sy; r.R2C1 = -sx; r.R2C2 = cx*cy; r.R2C3 = 0; - r.R3C0 = 0; r.R3C1 = 0; r.R3C2 = 0; r.R3C3 = 1; + Quaternion quaternion; + Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out quaternion); + CreateFromQuaternion(ref quaternion, out r); } // http://msdn.microsoft.com/en-us/library/bb205351(v=vs.85).aspx @@ -1735,66 +1731,66 @@ static Vector4 () { [MI(O.AggressiveInlining)] public static Single LengthSquared (Vector4 v) { Single r; LengthSquared (ref v, out r); return r; } } - /// - /// Provides maths functions with consistent function signatures across supported precisions. - /// - public static class Maths { - public static readonly Single Epsilon = 0.000001f; - public static readonly Single E = 2.71828182845904523536028747135f; - public static readonly Single Half = 0.5f; - public static readonly Single Quarter = 0.25f; - public static readonly Single Log10E = 0.43429448190325182765112891892f; - public static readonly Single Log2E = 1.44269504088896340735992468100f; - public static readonly Single Pi = 3.14159265358979323846264338328f; - public static readonly Single HalfPi = 1.57079632679489661923132169164f; - public static readonly Single QuarterPi = 0.78539816339744830961566084582f; - public static readonly Single Root2 = 1.41421356237309504880168872421f; - public static readonly Single Root3 = 1.73205080756887729352744634151f; - public static readonly Single Tau = 6.28318530717958647692528676656f; - public static readonly Single Deg2Rad = 0.01745329251994329576923690768f; - public static readonly Single Rad2Deg = 57.29577951308232087679815481409f; - public static readonly Single Zero = 0.0f; - public static readonly Single One = 1.0f; - - [MI(O.AggressiveInlining)] public static Single Sqrt (Single v) { return (Single) Math.Sqrt (v); } - [MI(O.AggressiveInlining)] public static Single Abs (Single v) { return (Single) Math.Abs (v); } - - [MI(O.AggressiveInlining)] public static Single Sin (Single v) { return (Single) Math.Sin (v); } - [MI(O.AggressiveInlining)] public static Single Cos (Single v) { return (Single) Math.Cos (v); } - [MI(O.AggressiveInlining)] public static Single Tan (Single v) { return (Single) Math.Tan (v); } - [MI(O.AggressiveInlining)] public static Single ArcCos (Single v) { return (Single) Math.Acos (v); } - [MI(O.AggressiveInlining)] public static Single ArcSin (Single v) { return (Single) Math.Asin (v); } - [MI(O.AggressiveInlining)] public static Single ArcTan (Single v) { return (Single) Math.Atan (v); } - [MI(O.AggressiveInlining)] public static Single ArcTan2 (Single y, Single x) { return (Single) Math.Atan2 (y, x); } - - - [MI(O.AggressiveInlining)] public static Single ToRadians (Single input) { return input * Deg2Rad; } - [MI(O.AggressiveInlining)] public static Single ToDegrees (Single input) { return input * Rad2Deg; } - [MI(O.AggressiveInlining)] public static Single FromFraction (Int32 numerator, Int32 denominator) { return (Single) numerator / (Single) denominator; } - [MI(O.AggressiveInlining)] public static Single FromFraction (Int64 numerator, Int64 denominator) { return (Single) numerator / (Single) denominator; } - - [MI(O.AggressiveInlining)] public static Single Min (Single a, Single b) { return a < b ? a : b; } - [MI(O.AggressiveInlining)] public static Single Max (Single a, Single b) { return a > b ? a : b; } - [MI(O.AggressiveInlining)] public static Single Clamp (Single value, Single min, Single max) { if (value < min) return min; else if (value > max) return max; else return value; } - [MI(O.AggressiveInlining)] public static Single Lerp (Single a, Single b, Single t) { return a + ((b - a) * t); } - - [MI(O.AggressiveInlining)] public static Single FromString (String str) { Single result = Zero; Single.TryParse (str, out result); return result; } - [MI(O.AggressiveInlining)] public static void FromString (String str, out Single value) { Single.TryParse (str, out value); } - - [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Single value) { return Abs(value) < Epsilon; } - [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Single a, Single b) { Single num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } - - [MI(O.AggressiveInlining)] public static Int32 Sign (Single value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } - [MI(O.AggressiveInlining)] public static Single CopySign (Single x, Single y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } - } - - - internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx - public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { - positions = positions & 0x1F; - uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); - uint wrapped = number >> (32 - positions); - return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); - } - } -} + /// + /// Provides maths functions with consistent function signatures across supported precisions. + /// + public static class Maths { + public static readonly Single Epsilon = 0.000001f; + public static readonly Single E = 2.71828182845904523536028747135f; + public static readonly Single Half = 0.5f; + public static readonly Single Quarter = 0.25f; + public static readonly Single Log10E = 0.43429448190325182765112891892f; + public static readonly Single Log2E = 1.44269504088896340735992468100f; + public static readonly Single Pi = 3.14159265358979323846264338328f; + public static readonly Single HalfPi = 1.57079632679489661923132169164f; + public static readonly Single QuarterPi = 0.78539816339744830961566084582f; + public static readonly Single Root2 = 1.41421356237309504880168872421f; + public static readonly Single Root3 = 1.73205080756887729352744634151f; + public static readonly Single Tau = 6.28318530717958647692528676656f; + public static readonly Single Deg2Rad = 0.01745329251994329576923690768f; + public static readonly Single Rad2Deg = 57.29577951308232087679815481409f; + public static readonly Single Zero = 0.0f; + public static readonly Single One = 1.0f; + + [MI(O.AggressiveInlining)] public static Single Sqrt (Single v) { return (Single) Math.Sqrt (v); } + [MI(O.AggressiveInlining)] public static Single Abs (Single v) { return (Single) Math.Abs (v); } + + [MI(O.AggressiveInlining)] public static Single Sin (Single v) { return (Single) Math.Sin (v); } + [MI(O.AggressiveInlining)] public static Single Cos (Single v) { return (Single) Math.Cos (v); } + [MI(O.AggressiveInlining)] public static Single Tan (Single v) { return (Single) Math.Tan (v); } + [MI(O.AggressiveInlining)] public static Single ArcCos (Single v) { return (Single) Math.Acos (v); } + [MI(O.AggressiveInlining)] public static Single ArcSin (Single v) { return (Single) Math.Asin (v); } + [MI(O.AggressiveInlining)] public static Single ArcTan (Single v) { return (Single) Math.Atan (v); } + [MI(O.AggressiveInlining)] public static Single ArcTan2 (Single y, Single x) { return (Single) Math.Atan2 (y, x); } + + + [MI(O.AggressiveInlining)] public static Single ToRadians (Single input) { return input * Deg2Rad; } + [MI(O.AggressiveInlining)] public static Single ToDegrees (Single input) { return input * Rad2Deg; } + [MI(O.AggressiveInlining)] public static Single FromFraction (Int32 numerator, Int32 denominator) { return (Single) numerator / (Single) denominator; } + [MI(O.AggressiveInlining)] public static Single FromFraction (Int64 numerator, Int64 denominator) { return (Single) numerator / (Single) denominator; } + + [MI(O.AggressiveInlining)] public static Single Min (Single a, Single b) { return a < b ? a : b; } + [MI(O.AggressiveInlining)] public static Single Max (Single a, Single b) { return a > b ? a : b; } + [MI(O.AggressiveInlining)] public static Single Clamp (Single value, Single min, Single max) { if (value < min) return min; else if (value > max) return max; else return value; } + [MI(O.AggressiveInlining)] public static Single Lerp (Single a, Single b, Single t) { return a + ((b - a) * t); } + + [MI(O.AggressiveInlining)] public static Single FromString (String str) { Single result = Zero; Single.TryParse (str, out result); return result; } + [MI(O.AggressiveInlining)] public static void FromString (String str, out Single value) { Single.TryParse (str, out value); } + + [MI(O.AggressiveInlining)] public static Boolean IsApproximatelyZero (Single value) { return Abs(value) < Epsilon; } + [MI(O.AggressiveInlining)] public static Boolean ApproximateEquals (Single a, Single b) { Single num = a - b; return ((-Epsilon <= num) && (num <= Epsilon)); } + + [MI(O.AggressiveInlining)] public static Int32 Sign (Single value) { if (value > 0) return 1; else if (value < 0) return -1; return 0; } + [MI(O.AggressiveInlining)] public static Single CopySign (Single x, Single y) { if ((x >= 0 && y >= 0) || (x <= 0 && y <= 0)) return x; else return -x; } + } + + + internal static class Int32Extensions { // http://msdn.microsoft.com/en-us/library/system.object.gethashcode(v=vs.110).aspx + public static Int32 ShiftAndWrap (this Int32 value, Int32 positions = 2) { + positions = positions & 0x1F; + uint number = BitConverter.ToUInt32 (BitConverter.GetBytes(value), 0); + uint wrapped = number >> (32 - positions); + return BitConverter.ToInt32 (BitConverter.GetBytes ((number << positions) | wrapped), 0); + } + } +} diff --git a/source/abacus/src/test/Abacus.Double.Tests.cs b/source/abacus/src/test/Abacus.Double.Tests.cs index cde3de4..2d1948e 100644 --- a/source/abacus/src/test/Abacus.Double.Tests.cs +++ b/source/abacus/src/test/Abacus.Double.Tests.cs @@ -1,238 +1,238 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Collections.Generic; -using NUnit.Framework; - -namespace Abacus.DoublePrecision { - +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Collections.Generic; +using NUnit.Framework; + +namespace Abacus.DoublePrecision { + [TestFixture] public class MathsTests { - public static readonly Double TestTolerance = 0.000001; - public static readonly Double PercentageTolerance = 0.0000001; + public static readonly Double TestTolerance = 0.000001; + public static readonly Double PercentageTolerance = 0.0000001; + + + } + + [TestFixture] + public class Vector2Tests { + static readonly Random rand = new Random(0); + + static Double GetNextRandomDouble () { + Double randomValue = (Double) rand.NextDouble(); + Double multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector2 GetNextRandomVector2 () { + Double a = GetNextRandomDouble(); + Double b = GetNextRandomDouble(); + return new Vector2(a, b); + } + + static void AssertEqualWithinReason (Vector2 a, Vector2 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + } + + [Test] + public void TestMemberFn_GetHashCode_i () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector2(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector3Tests { + static readonly Random rand = new Random(0); + + static Double GetNextRandomDouble () { + Double randomValue = (Double) rand.NextDouble(); + Double multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + static Vector3 GetNextRandomVector3 () { + Double a = GetNextRandomDouble(); + Double b = GetNextRandomDouble(); + Double c = GetNextRandomDouble(); + return new Vector3(a, b, c); + } + static void AssertEqualWithinReason (Vector3 a, Vector3 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector3(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector4Tests { + static readonly Random rand = new Random(0); + + static Double GetNextRandomDouble () { + Double randomValue = (Double) rand.NextDouble(); + Double multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector4 GetNextRandomVector4 () { + Double a = GetNextRandomDouble(); + Double b = GetNextRandomDouble(); + Double c = GetNextRandomDouble(); + Double d = GetNextRandomDouble(); + return new Vector4(a, b, c, d); + } + + static void AssertEqualWithinReason (Vector4 a, Vector4 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector4(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class QuaternionTests { + static readonly Random rand = new Random(0); + + static Double GetNextRandomDouble () { + Double randomValue = (Double) rand.NextDouble(); + Double multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + internal static Quaternion GetNextRandomQuaternion () { + Double yaw = Maths.Pi * (Double) rand.Next(0, 360) / (Double) 180; + Double pitch = Maths.Pi * (Double) rand.Next(0, 360) / (Double) 180; + Double roll = Maths.Pi * (Double) rand.Next(0, 360) / (Double) 180; + Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); + return q; + } + + internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { + Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); + Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); + Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); + Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); + } + + internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { + Boolean pass1 = + Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; + + Quaternion c; + Quaternion.Negate (ref b, out c); + + Boolean pass2 = + Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; + + Assert.That(pass1 || pass2, Is.EqualTo (true)); + } + + [Test] + public void TestMemberFn_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomQuaternion(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } } - [TestFixture] - public class Vector2Tests { - static readonly Random rand = new Random(0); - - static Double GetNextRandomDouble () { - Double randomValue = (Double) rand.NextDouble(); - Double multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector2 GetNextRandomVector2 () { - Double a = GetNextRandomDouble(); - Double b = GetNextRandomDouble(); - return new Vector2(a, b); - } - - static void AssertEqualWithinReason (Vector2 a, Vector2 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - } - - [Test] - public void TestMemberFn_GetHashCode_i () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector2(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector3Tests { - static readonly Random rand = new Random(0); - - static Double GetNextRandomDouble () { - Double randomValue = (Double) rand.NextDouble(); - Double multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector3 GetNextRandomVector3 () { - Double a = GetNextRandomDouble(); - Double b = GetNextRandomDouble(); - Double c = GetNextRandomDouble(); - return new Vector3(a, b, c); - } - - static void AssertEqualWithinReason (Vector3 a, Vector3 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector3(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector4Tests { - static readonly Random rand = new Random(0); - - static Double GetNextRandomDouble () { - Double randomValue = (Double) rand.NextDouble(); - Double multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector4 GetNextRandomVector4 () { - Double a = GetNextRandomDouble(); - Double b = GetNextRandomDouble(); - Double c = GetNextRandomDouble(); - Double d = GetNextRandomDouble(); - return new Vector4(a, b, c, d); - } - - static void AssertEqualWithinReason (Vector4 a, Vector4 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector4(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class QuaternionTests { - static readonly Random rand = new Random(0); - - static Double GetNextRandomDouble () { - Double randomValue = (Double) rand.NextDouble(); - Double multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - internal static Quaternion GetNextRandomQuaternion () { - Double yaw = Maths.Pi * (Double) rand.Next(0, 360) / (Double) 180; - Double pitch = Maths.Pi * (Double) rand.Next(0, 360) / (Double) 180; - Double roll = Maths.Pi * (Double) rand.Next(0, 360) / (Double) 180; - Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); - return q; - } - - internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { - Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); - Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); - Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); - Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); - } - - internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { - Boolean pass1 = - Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; - - Quaternion c; - Quaternion.Negate (ref b, out c); - - Boolean pass2 = - Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; - - Assert.That(pass1 || pass2, Is.EqualTo (true)); - } - - [Test] - public void TestMemberFn_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomQuaternion(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] public class Matrix44Tests { static readonly Random rand = new Random(0); @@ -298,4 +298,4 @@ public void TestMemberFn_GetHashCode () { Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); } } -} +} diff --git a/source/abacus/src/test/Abacus.Fixed32.Tests.cs b/source/abacus/src/test/Abacus.Fixed32.Tests.cs index 8fb99e0..5dd3df2 100644 --- a/source/abacus/src/test/Abacus.Fixed32.Tests.cs +++ b/source/abacus/src/test/Abacus.Fixed32.Tests.cs @@ -1,56 +1,56 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Collections.Generic; -using NUnit.Framework; - -namespace Abacus.Fixed32Precision { - +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Collections.Generic; +using NUnit.Framework; + +namespace Abacus.Fixed32Precision { + [TestFixture] public class Fixed32Tests { @@ -567,8 +567,8 @@ public void TestArcTan2 () { [TestFixture] public class MathsTests { - public static readonly Double TestTolerance = 0.1; - public static readonly Double PercentageTolerance = 0.01; + public static readonly Double TestTolerance = 0.1; + public static readonly Double PercentageTolerance = 0.01; [Test] public void TestConstants () { @@ -592,180 +592,180 @@ public void TestConstants () { } - [TestFixture] - public class Vector2Tests { - static readonly Random rand = new Random(0); - - static Fixed32 GetNextRandomFixed32 () { - Fixed32 randomValue = (Fixed32) rand.NextDouble(); - Fixed32 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector2 GetNextRandomVector2 () { - Fixed32 a = GetNextRandomFixed32(); - Fixed32 b = GetNextRandomFixed32(); - return new Vector2(a, b); - } - - static void AssertEqualWithinReason (Vector2 a, Vector2 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - } - - [Test] - public void TestMemberFn_GetHashCode_i () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector2(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector3Tests { - static readonly Random rand = new Random(0); - - static Fixed32 GetNextRandomFixed32 () { - Fixed32 randomValue = (Fixed32) rand.NextDouble(); - Fixed32 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector3 GetNextRandomVector3 () { - Fixed32 a = GetNextRandomFixed32(); - Fixed32 b = GetNextRandomFixed32(); - Fixed32 c = GetNextRandomFixed32(); - return new Vector3(a, b, c); - } - - static void AssertEqualWithinReason (Vector3 a, Vector3 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector3(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector4Tests { - static readonly Random rand = new Random(0); - - static Fixed32 GetNextRandomFixed32 () { - Fixed32 randomValue = (Fixed32) rand.NextDouble(); - Fixed32 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector4 GetNextRandomVector4 () { - Fixed32 a = GetNextRandomFixed32(); - Fixed32 b = GetNextRandomFixed32(); - Fixed32 c = GetNextRandomFixed32(); - Fixed32 d = GetNextRandomFixed32(); - return new Vector4(a, b, c, d); - } - - static void AssertEqualWithinReason (Vector4 a, Vector4 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector4(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class QuaternionTests { - static readonly Random rand = new Random(0); - - static Fixed32 GetNextRandomFixed32 () { - Fixed32 randomValue = (Fixed32) rand.NextDouble(); - Fixed32 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - internal static Quaternion GetNextRandomQuaternion () { - Fixed32 yaw = Maths.Pi * (Fixed32) rand.Next(0, 360) / (Fixed32) 180; - Fixed32 pitch = Maths.Pi * (Fixed32) rand.Next(0, 360) / (Fixed32) 180; - Fixed32 roll = Maths.Pi * (Fixed32) rand.Next(0, 360) / (Fixed32) 180; - Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); - return q; - } - - internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { - Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); - Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); - Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); - Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); - } - - internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { - Boolean pass1 = - Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; - - Quaternion c; - Quaternion.Negate (ref b, out c); - - Boolean pass2 = - Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; - - Assert.That(pass1 || pass2, Is.EqualTo (true)); - } - - [Test] - public void TestMemberFn_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomQuaternion(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - + [TestFixture] + public class Vector2Tests { + static readonly Random rand = new Random(0); + + static Fixed32 GetNextRandomFixed32 () { + Fixed32 randomValue = (Fixed32) rand.NextDouble(); + Fixed32 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector2 GetNextRandomVector2 () { + Fixed32 a = GetNextRandomFixed32(); + Fixed32 b = GetNextRandomFixed32(); + return new Vector2(a, b); + } + + static void AssertEqualWithinReason (Vector2 a, Vector2 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + } + + [Test] + public void TestMemberFn_GetHashCode_i () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector2(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector3Tests { + static readonly Random rand = new Random(0); + + static Fixed32 GetNextRandomFixed32 () { + Fixed32 randomValue = (Fixed32) rand.NextDouble(); + Fixed32 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector3 GetNextRandomVector3 () { + Fixed32 a = GetNextRandomFixed32(); + Fixed32 b = GetNextRandomFixed32(); + Fixed32 c = GetNextRandomFixed32(); + return new Vector3(a, b, c); + } + + static void AssertEqualWithinReason (Vector3 a, Vector3 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector3(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector4Tests { + static readonly Random rand = new Random(0); + + static Fixed32 GetNextRandomFixed32 () { + Fixed32 randomValue = (Fixed32) rand.NextDouble(); + Fixed32 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector4 GetNextRandomVector4 () { + Fixed32 a = GetNextRandomFixed32(); + Fixed32 b = GetNextRandomFixed32(); + Fixed32 c = GetNextRandomFixed32(); + Fixed32 d = GetNextRandomFixed32(); + return new Vector4(a, b, c, d); + } + + static void AssertEqualWithinReason (Vector4 a, Vector4 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector4(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class QuaternionTests { + static readonly Random rand = new Random(0); + + static Fixed32 GetNextRandomFixed32 () { + Fixed32 randomValue = (Fixed32) rand.NextDouble(); + Fixed32 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + internal static Quaternion GetNextRandomQuaternion () { + Fixed32 yaw = Maths.Pi * (Fixed32) rand.Next(0, 360) / (Fixed32) 180; + Fixed32 pitch = Maths.Pi * (Fixed32) rand.Next(0, 360) / (Fixed32) 180; + Fixed32 roll = Maths.Pi * (Fixed32) rand.Next(0, 360) / (Fixed32) 180; + Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); + return q; + } + + internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { + Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); + Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); + Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); + Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); + } + + internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { + Boolean pass1 = + Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; + + Quaternion c; + Quaternion.Negate (ref b, out c); + + Boolean pass2 = + Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; + + Assert.That(pass1 || pass2, Is.EqualTo (true)); + } + + [Test] + public void TestMemberFn_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomQuaternion(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] public class Matrix44Tests { static readonly Random rand = new Random(0); @@ -831,4 +831,4 @@ public void TestMemberFn_GetHashCode () { Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); } } -} +} diff --git a/source/abacus/src/test/Abacus.Fixed64.Tests.cs b/source/abacus/src/test/Abacus.Fixed64.Tests.cs index 4b74c5d..2cafed5 100644 --- a/source/abacus/src/test/Abacus.Fixed64.Tests.cs +++ b/source/abacus/src/test/Abacus.Fixed64.Tests.cs @@ -1,56 +1,56 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Collections.Generic; -using NUnit.Framework; - -namespace Abacus.Fixed64Precision { - +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Collections.Generic; +using NUnit.Framework; + +namespace Abacus.Fixed64Precision { + [TestFixture] public class Fixed64Tests { @@ -567,8 +567,8 @@ public void TestArcTan2 () { [TestFixture] public class MathsTests { - public static readonly Double TestTolerance = 0.01; - public static readonly Double PercentageTolerance = 0.0001; + public static readonly Double TestTolerance = 0.01; + public static readonly Double PercentageTolerance = 0.0001; [Test] public void TestConstants () { @@ -592,180 +592,180 @@ public void TestConstants () { } - [TestFixture] - public class Vector2Tests { - static readonly Random rand = new Random(0); - - static Fixed64 GetNextRandomFixed64 () { - Fixed64 randomValue = (Fixed64) rand.NextDouble(); - Fixed64 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector2 GetNextRandomVector2 () { - Fixed64 a = GetNextRandomFixed64(); - Fixed64 b = GetNextRandomFixed64(); - return new Vector2(a, b); - } - - static void AssertEqualWithinReason (Vector2 a, Vector2 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - } - - [Test] - public void TestMemberFn_GetHashCode_i () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector2(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector3Tests { - static readonly Random rand = new Random(0); - - static Fixed64 GetNextRandomFixed64 () { - Fixed64 randomValue = (Fixed64) rand.NextDouble(); - Fixed64 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector3 GetNextRandomVector3 () { - Fixed64 a = GetNextRandomFixed64(); - Fixed64 b = GetNextRandomFixed64(); - Fixed64 c = GetNextRandomFixed64(); - return new Vector3(a, b, c); - } - - static void AssertEqualWithinReason (Vector3 a, Vector3 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector3(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector4Tests { - static readonly Random rand = new Random(0); - - static Fixed64 GetNextRandomFixed64 () { - Fixed64 randomValue = (Fixed64) rand.NextDouble(); - Fixed64 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector4 GetNextRandomVector4 () { - Fixed64 a = GetNextRandomFixed64(); - Fixed64 b = GetNextRandomFixed64(); - Fixed64 c = GetNextRandomFixed64(); - Fixed64 d = GetNextRandomFixed64(); - return new Vector4(a, b, c, d); - } - - static void AssertEqualWithinReason (Vector4 a, Vector4 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector4(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class QuaternionTests { - static readonly Random rand = new Random(0); - - static Fixed64 GetNextRandomFixed64 () { - Fixed64 randomValue = (Fixed64) rand.NextDouble(); - Fixed64 multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - internal static Quaternion GetNextRandomQuaternion () { - Fixed64 yaw = Maths.Pi * (Fixed64) rand.Next(0, 360) / (Fixed64) 180; - Fixed64 pitch = Maths.Pi * (Fixed64) rand.Next(0, 360) / (Fixed64) 180; - Fixed64 roll = Maths.Pi * (Fixed64) rand.Next(0, 360) / (Fixed64) 180; - Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); - return q; - } - - internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { - Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); - Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); - Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); - Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); - } - - internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { - Boolean pass1 = - Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; - - Quaternion c; - Quaternion.Negate (ref b, out c); - - Boolean pass2 = - Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; - - Assert.That(pass1 || pass2, Is.EqualTo (true)); - } - - [Test] - public void TestMemberFn_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomQuaternion(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - + [TestFixture] + public class Vector2Tests { + static readonly Random rand = new Random(0); + + static Fixed64 GetNextRandomFixed64 () { + Fixed64 randomValue = (Fixed64) rand.NextDouble(); + Fixed64 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector2 GetNextRandomVector2 () { + Fixed64 a = GetNextRandomFixed64(); + Fixed64 b = GetNextRandomFixed64(); + return new Vector2(a, b); + } + + static void AssertEqualWithinReason (Vector2 a, Vector2 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + } + + [Test] + public void TestMemberFn_GetHashCode_i () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector2(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector3Tests { + static readonly Random rand = new Random(0); + + static Fixed64 GetNextRandomFixed64 () { + Fixed64 randomValue = (Fixed64) rand.NextDouble(); + Fixed64 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector3 GetNextRandomVector3 () { + Fixed64 a = GetNextRandomFixed64(); + Fixed64 b = GetNextRandomFixed64(); + Fixed64 c = GetNextRandomFixed64(); + return new Vector3(a, b, c); + } + + static void AssertEqualWithinReason (Vector3 a, Vector3 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector3(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector4Tests { + static readonly Random rand = new Random(0); + + static Fixed64 GetNextRandomFixed64 () { + Fixed64 randomValue = (Fixed64) rand.NextDouble(); + Fixed64 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector4 GetNextRandomVector4 () { + Fixed64 a = GetNextRandomFixed64(); + Fixed64 b = GetNextRandomFixed64(); + Fixed64 c = GetNextRandomFixed64(); + Fixed64 d = GetNextRandomFixed64(); + return new Vector4(a, b, c, d); + } + + static void AssertEqualWithinReason (Vector4 a, Vector4 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector4(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class QuaternionTests { + static readonly Random rand = new Random(0); + + static Fixed64 GetNextRandomFixed64 () { + Fixed64 randomValue = (Fixed64) rand.NextDouble(); + Fixed64 multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + internal static Quaternion GetNextRandomQuaternion () { + Fixed64 yaw = Maths.Pi * (Fixed64) rand.Next(0, 360) / (Fixed64) 180; + Fixed64 pitch = Maths.Pi * (Fixed64) rand.Next(0, 360) / (Fixed64) 180; + Fixed64 roll = Maths.Pi * (Fixed64) rand.Next(0, 360) / (Fixed64) 180; + Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); + return q; + } + + internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { + Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); + Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); + Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); + Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); + } + + internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { + Boolean pass1 = + Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; + + Quaternion c; + Quaternion.Negate (ref b, out c); + + Boolean pass2 = + Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; + + Assert.That(pass1 || pass2, Is.EqualTo (true)); + } + + [Test] + public void TestMemberFn_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomQuaternion(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] public class Matrix44Tests { static readonly Random rand = new Random(0); @@ -831,4 +831,4 @@ public void TestMemberFn_GetHashCode () { Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); } } -} +} diff --git a/source/abacus/src/test/Abacus.Single.Tests.cs b/source/abacus/src/test/Abacus.Single.Tests.cs index 53136f2..344a17c 100644 --- a/source/abacus/src/test/Abacus.Single.Tests.cs +++ b/source/abacus/src/test/Abacus.Single.Tests.cs @@ -1,238 +1,238 @@ -// ┌────────────────────────────────────────────────────────────────────────┐ \\ -// │ _____ ___. │ \\ -// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ -// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ -// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ -// │ \____|__ /___ (____ /\___ >____//____ > │ \\ -// │ \/ \/ \/ \/ \/ v1.1.0 │ \\ -// │ │ \\ -// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ -// │ │ \\ -// │ ________________________________________________________ │ \\ -// │ / ____________________________________________________ \ │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ -// │ | ____________________________________________________ | │ \\ -// │ | | | | | | | | | | | | | | | | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ -// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ -// │ \________________________________________________________/ │ \\ -// │ │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Copyright © 2012 - 2020 Ash Pook │ \\ -// ├────────────────────────────────────────────────────────────────────────┤ \\ -// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ -// │ a copy of this software and associated documentation files (the │ \\ -// │ "Software"), to deal in the Software without restriction, including │ \\ -// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ -// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ -// │ permit persons to whom the Software is furnished to do so, subject to │ \\ -// │ the following conditions: │ \\ -// │ │ \\ -// │ The above copyright notice and this permission notice shall be │ \\ -// │ included in all copies or substantial portions of the Software. │ \\ -// │ │ \\ -// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ -// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ -// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ -// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ -// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ -// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ -// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ -// └────────────────────────────────────────────────────────────────────────┘ \\ - -using System; -using System.Collections.Generic; -using NUnit.Framework; - -namespace Abacus.SinglePrecision { - +// ┌────────────────────────────────────────────────────────────────────────┐ \\ +// │ _____ ___. │ \\ +// │ / _ \\_ |__ _____ ____ __ __ ______ │ \\ +// │ / /_\ \| __ \\__ \ _/ ___\| | \/ ___/ │ \\ +// │ / | \ \_\ \/ __ \\ \___| | /\___ \ │ \\ +// │ \____|__ /___ (____ /\___ >____//____ > │ \\ +// │ \/ \/ \/ \/ \/ v1.1.1 │ \\ +// │ │ \\ +// │ Fast, efficient, cross platform, cross precision, maths library. │ \\ +// │ │ \\ +// │ ________________________________________________________ │ \\ +// │ / ____________________________________________________ \ │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |_|___|___|___|___|___|___|___|___|___|___|___|___|__| | │ \\ +// │ | ____________________________________________________ | │ \\ +// │ | | | | | | | | | | | | | | | | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> <_> | | │ \\ +// │ | |<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_<_>_| | │ \\ +// │ \________________________________________________________/ │ \\ +// │ │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Copyright © 2012 - 2022 Ash Pook │ \\ +// ├────────────────────────────────────────────────────────────────────────┤ \\ +// │ Permission is hereby granted, free of charge, to any person obtaining │ \\ +// │ a copy of this software and associated documentation files (the │ \\ +// │ "Software"), to deal in the Software without restriction, including │ \\ +// │ without limitation the rights to use, copy, modify, merge, publish, │ \\ +// │ distribute, sublicense, and/or sellcopies of the Software, and to │ \\ +// │ permit persons to whom the Software is furnished to do so, subject to │ \\ +// │ the following conditions: │ \\ +// │ │ \\ +// │ The above copyright notice and this permission notice shall be │ \\ +// │ included in all copies or substantial portions of the Software. │ \\ +// │ │ \\ +// │ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, │ \\ +// │ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF │ \\ +// │ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ \\ +// │ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY │ \\ +// │ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, │ \\ +// │ TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE │ \\ +// │ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ \\ +// └────────────────────────────────────────────────────────────────────────┘ \\ + +using System; +using System.Collections.Generic; +using NUnit.Framework; + +namespace Abacus.SinglePrecision { + [TestFixture] public class MathsTests { - public static readonly Double TestTolerance = 0.00001; - public static readonly Double PercentageTolerance = 0.000001; + public static readonly Double TestTolerance = 0.00001; + public static readonly Double PercentageTolerance = 0.000001; + + + } + + [TestFixture] + public class Vector2Tests { + static readonly Random rand = new Random(0); + + static Single GetNextRandomSingle () { + Single randomValue = (Single) rand.NextDouble(); + Single multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector2 GetNextRandomVector2 () { + Single a = GetNextRandomSingle(); + Single b = GetNextRandomSingle(); + return new Vector2(a, b); + } + + static void AssertEqualWithinReason (Vector2 a, Vector2 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + } + + [Test] + public void TestMemberFn_GetHashCode_i () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector2(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector3Tests { + static readonly Random rand = new Random(0); + + static Single GetNextRandomSingle () { + Single randomValue = (Single) rand.NextDouble(); + Single multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + static Vector3 GetNextRandomVector3 () { + Single a = GetNextRandomSingle(); + Single b = GetNextRandomSingle(); + Single c = GetNextRandomSingle(); + return new Vector3(a, b, c); + } + static void AssertEqualWithinReason (Vector3 a, Vector3 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector3(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class Vector4Tests { + static readonly Random rand = new Random(0); + + static Single GetNextRandomSingle () { + Single randomValue = (Single) rand.NextDouble(); + Single multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + static Vector4 GetNextRandomVector4 () { + Single a = GetNextRandomSingle(); + Single b = GetNextRandomSingle(); + Single c = GetNextRandomSingle(); + Single d = GetNextRandomSingle(); + return new Vector4(a, b, c, d); + } + + static void AssertEqualWithinReason (Vector4 a, Vector4 b) { + Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); + Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); + Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); + Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); + } + + [Test] + public void Test_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomVector4(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } + } + [TestFixture] + public class QuaternionTests { + static readonly Random rand = new Random(0); + + static Single GetNextRandomSingle () { + Single randomValue = (Single) rand.NextDouble(); + Single multiplier = 1000; + randomValue *= multiplier; + Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; + if (randomBoolean) randomValue = 0 - randomValue; + return randomValue; + } + + internal static Quaternion GetNextRandomQuaternion () { + Single yaw = Maths.Pi * (Single) rand.Next(0, 360) / (Single) 180; + Single pitch = Maths.Pi * (Single) rand.Next(0, 360) / (Single) 180; + Single roll = Maths.Pi * (Single) rand.Next(0, 360) / (Single) 180; + Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); + return q; + } + + internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { + Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); + Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); + Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); + Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); + } + + internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { + Boolean pass1 = + Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; + + Quaternion c; + Quaternion.Negate (ref b, out c); + + Boolean pass2 = + Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && + Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && + Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && + Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; + + Assert.That(pass1 || pass2, Is.EqualTo (true)); + } + + [Test] + public void TestMemberFn_GetHashCode () { + var hs1 = new HashSet(); + var hs2 = new HashSet(); + for(Int32 i = 0; i < 10000; ++i) { + var a = GetNextRandomQuaternion(); + hs1.Add(a); + hs2.Add(a.GetHashCode()); + } + Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); + } } - [TestFixture] - public class Vector2Tests { - static readonly Random rand = new Random(0); - - static Single GetNextRandomSingle () { - Single randomValue = (Single) rand.NextDouble(); - Single multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector2 GetNextRandomVector2 () { - Single a = GetNextRandomSingle(); - Single b = GetNextRandomSingle(); - return new Vector2(a, b); - } - - static void AssertEqualWithinReason (Vector2 a, Vector2 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - } - - [Test] - public void TestMemberFn_GetHashCode_i () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector2(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector3Tests { - static readonly Random rand = new Random(0); - - static Single GetNextRandomSingle () { - Single randomValue = (Single) rand.NextDouble(); - Single multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector3 GetNextRandomVector3 () { - Single a = GetNextRandomSingle(); - Single b = GetNextRandomSingle(); - Single c = GetNextRandomSingle(); - return new Vector3(a, b, c); - } - - static void AssertEqualWithinReason (Vector3 a, Vector3 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector3(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class Vector4Tests { - static readonly Random rand = new Random(0); - - static Single GetNextRandomSingle () { - Single randomValue = (Single) rand.NextDouble(); - Single multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - static Vector4 GetNextRandomVector4 () { - Single a = GetNextRandomSingle(); - Single b = GetNextRandomSingle(); - Single c = GetNextRandomSingle(); - Single d = GetNextRandomSingle(); - return new Vector4(a, b, c, d); - } - - static void AssertEqualWithinReason (Vector4 a, Vector4 b) { - Assert.That(a.X, Is.EqualTo(b.X).Within(MathsTests.TestTolerance)); - Assert.That(a.Y, Is.EqualTo(b.Y).Within(MathsTests.TestTolerance)); - Assert.That(a.Z, Is.EqualTo(b.Z).Within(MathsTests.TestTolerance)); - Assert.That(a.W, Is.EqualTo(b.W).Within(MathsTests.TestTolerance)); - } - - [Test] - public void Test_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomVector4(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] - public class QuaternionTests { - static readonly Random rand = new Random(0); - - static Single GetNextRandomSingle () { - Single randomValue = (Single) rand.NextDouble(); - Single multiplier = 1000; - randomValue *= multiplier; - Boolean randomBoolean = (rand.Next(0, 1) == 0) ? true : false; - if (randomBoolean) randomValue = 0 - randomValue; - return randomValue; - } - - internal static Quaternion GetNextRandomQuaternion () { - Single yaw = Maths.Pi * (Single) rand.Next(0, 360) / (Single) 180; - Single pitch = Maths.Pi * (Single) rand.Next(0, 360) / (Single) 180; - Single roll = Maths.Pi * (Single) rand.Next(0, 360) / (Single) 180; - Quaternion q; Quaternion.CreateFromYawPitchRoll(ref yaw, ref pitch, ref roll, out q); - return q; - } - - internal static void AssertEqualWithinReason (Quaternion a, Quaternion b) { - Assert.That(a.I, Is.EqualTo(b.I).Within(MathsTests.TestTolerance)); - Assert.That(a.J, Is.EqualTo(b.J).Within(MathsTests.TestTolerance)); - Assert.That(a.K, Is.EqualTo(b.K).Within(MathsTests.TestTolerance)); - Assert.That(a.U, Is.EqualTo(b.U).Within(MathsTests.TestTolerance)); - } - - internal static void AssertEqualOrNegatedWithinReason (Quaternion a, Quaternion b) { - Boolean pass1 = - Maths.Abs (a.I - b.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - b.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - b.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - b.U) <= MathsTests.TestTolerance; - - Quaternion c; - Quaternion.Negate (ref b, out c); - - Boolean pass2 = - Maths.Abs (a.I - c.I) <= MathsTests.TestTolerance && - Maths.Abs (a.J - c.J) <= MathsTests.TestTolerance && - Maths.Abs (a.K - c.K) <= MathsTests.TestTolerance && - Maths.Abs (a.U - c.U) <= MathsTests.TestTolerance; - - Assert.That(pass1 || pass2, Is.EqualTo (true)); - } - - [Test] - public void TestMemberFn_GetHashCode () { - var hs1 = new HashSet(); - var hs2 = new HashSet(); - for(Int32 i = 0; i < 10000; ++i) { - var a = GetNextRandomQuaternion(); - hs1.Add(a); - hs2.Add(a.GetHashCode()); - } - Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); - } - } - [TestFixture] public class Matrix44Tests { static readonly Random rand = new Random(0); @@ -298,4 +298,4 @@ public void TestMemberFn_GetHashCode () { Assert.That(hs1.Count, Is.EqualTo(hs2.Count).Within(10)); } } -} +}