From cda46fbb15a43665f7ab5e137f8c1fc46abb59d2 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Wed, 16 Aug 2023 14:18:22 -0600 Subject: [PATCH 01/10] bcl numberics library added --- .../Microsoft.Bcl.Numerics.sln | 74 + .../ref/Microsoft.Bcl.Numerics.Forwards.cs | 4 + .../ref/Microsoft.Bcl.Numerics.cs | 42 + .../ref/Microsoft.Bcl.Numerics.csproj | 11 + .../src/Microsoft.Bcl.Numerics.csproj | 25 + .../src/Resources/strings.resx | 126 ++ .../src/System/MathF.cs | 242 +++ .../Microsoft.Bcl.Numerics/src/strings.resx | 72 + .../Microsoft.Bcl.Numerics/tests/MathF.cs | 1577 +++++++++++++++++ .../tests/Microsoft.Bcl.Numerics.Tests.csproj | 12 + 10 files changed, 2185 insertions(+) create mode 100644 src/libraries/Microsoft.Bcl.Numerics/Microsoft.Bcl.Numerics.sln create mode 100644 src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.Forwards.cs create mode 100644 src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.cs create mode 100644 src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj create mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj create mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx create mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs create mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/strings.resx create mode 100644 src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs create mode 100644 src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj diff --git a/src/libraries/Microsoft.Bcl.Numerics/Microsoft.Bcl.Numerics.sln b/src/libraries/Microsoft.Bcl.Numerics/Microsoft.Bcl.Numerics.sln new file mode 100644 index 0000000000000..1192785b14a9f --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/Microsoft.Bcl.Numerics.sln @@ -0,0 +1,74 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{CAEE0409-CCC3-4EA6-AB54-177FD305D42D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.Numerics", "ref\Microsoft.Bcl.Numerics.csproj", "{73E7C25C-AEBC-4F4F-B8D1-0CC49D5B92DE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.Numerics", "src\Microsoft.Bcl.Numerics.csproj", "{4D4BED71-8904-4A74-88CD-63D002CCACD0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Bcl.Numerics.Tests", "tests\Microsoft.Bcl.Numerics.Tests.csproj", "{51D9518A-464D-4257-9567-3BDCFF24F3EE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ComInterfaceGenerator", "..\System.Runtime.InteropServices\gen\ComInterfaceGenerator\ComInterfaceGenerator.csproj", "{E30F71EB-6C3B-4052-84F7-36EAA178A45E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LibraryImportGenerator", "..\System.Runtime.InteropServices\gen\LibraryImportGenerator\LibraryImportGenerator.csproj", "{0AE44453-273B-4F0E-9901-A87891A73C1B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.SourceGeneration", "..\System.Runtime.InteropServices\gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj", "{D0F1936C-CF7C-4448-9F90-B9DEABE89EBB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{6614EF7F-23FC-4809-AFF5-1ADBF1B6422C}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ref", "ref", "{111B1B5B-A004-4C05-9A8C-E0931DADA5FB}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{85204CF5-0C88-4BBB-9E70-D8CCED82ED3D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "gen", "gen", "{D6A9108E-553B-445E-A037-FA4F3140A279}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CAEE0409-CCC3-4EA6-AB54-177FD305D42D}.Release|Any CPU.Build.0 = Release|Any CPU + {73E7C25C-AEBC-4F4F-B8D1-0CC49D5B92DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73E7C25C-AEBC-4F4F-B8D1-0CC49D5B92DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73E7C25C-AEBC-4F4F-B8D1-0CC49D5B92DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73E7C25C-AEBC-4F4F-B8D1-0CC49D5B92DE}.Release|Any CPU.Build.0 = Release|Any CPU + {4D4BED71-8904-4A74-88CD-63D002CCACD0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4D4BED71-8904-4A74-88CD-63D002CCACD0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4D4BED71-8904-4A74-88CD-63D002CCACD0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4D4BED71-8904-4A74-88CD-63D002CCACD0}.Release|Any CPU.Build.0 = Release|Any CPU + {51D9518A-464D-4257-9567-3BDCFF24F3EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51D9518A-464D-4257-9567-3BDCFF24F3EE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51D9518A-464D-4257-9567-3BDCFF24F3EE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51D9518A-464D-4257-9567-3BDCFF24F3EE}.Release|Any CPU.Build.0 = Release|Any CPU + {E30F71EB-6C3B-4052-84F7-36EAA178A45E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E30F71EB-6C3B-4052-84F7-36EAA178A45E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E30F71EB-6C3B-4052-84F7-36EAA178A45E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E30F71EB-6C3B-4052-84F7-36EAA178A45E}.Release|Any CPU.Build.0 = Release|Any CPU + {0AE44453-273B-4F0E-9901-A87891A73C1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AE44453-273B-4F0E-9901-A87891A73C1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AE44453-273B-4F0E-9901-A87891A73C1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AE44453-273B-4F0E-9901-A87891A73C1B}.Release|Any CPU.Build.0 = Release|Any CPU + {D0F1936C-CF7C-4448-9F90-B9DEABE89EBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D0F1936C-CF7C-4448-9F90-B9DEABE89EBB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D0F1936C-CF7C-4448-9F90-B9DEABE89EBB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D0F1936C-CF7C-4448-9F90-B9DEABE89EBB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {CAEE0409-CCC3-4EA6-AB54-177FD305D42D} = {6614EF7F-23FC-4809-AFF5-1ADBF1B6422C} + {51D9518A-464D-4257-9567-3BDCFF24F3EE} = {6614EF7F-23FC-4809-AFF5-1ADBF1B6422C} + {73E7C25C-AEBC-4F4F-B8D1-0CC49D5B92DE} = {111B1B5B-A004-4C05-9A8C-E0931DADA5FB} + {4D4BED71-8904-4A74-88CD-63D002CCACD0} = {85204CF5-0C88-4BBB-9E70-D8CCED82ED3D} + {E30F71EB-6C3B-4052-84F7-36EAA178A45E} = {D6A9108E-553B-445E-A037-FA4F3140A279} + {0AE44453-273B-4F0E-9901-A87891A73C1B} = {D6A9108E-553B-445E-A037-FA4F3140A279} + {D0F1936C-CF7C-4448-9F90-B9DEABE89EBB} = {D6A9108E-553B-445E-A037-FA4F3140A279} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A835CEDB-E9E2-49EE-8499-BD7FDD984E53} + EndGlobalSection +EndGlobal diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.Forwards.cs b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.Forwards.cs new file mode 100644 index 0000000000000..641ce5525675f --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.Forwards.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.MathF))] diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.cs b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.cs new file mode 100644 index 0000000000000..d952814464f67 --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// ------------------------------------------------------------------------------ +// Changes to this file must follow the https://aka.ms/api-review process. +// ------------------------------------------------------------------------------ + +namespace System +{ + public static partial class MathF + { + public const float E = 2.7182817f; + public const float PI = 3.1415927f; + public static float Abs(float x) { throw null; } + public static float Acos(float x) { throw null; } + public static float Asin(float x) { throw null; } + public static float Atan(float x) { throw null; } + public static float Atan2(float y, float x) { throw null; } + public static float Ceiling(float x) { throw null; } + public static float Cos(float x) { throw null; } + public static float Cosh(float x) { throw null; } + public static float Exp(float x) { throw null; } + public static float Floor(float x) { throw null; } + public static float IEEERemainder(float x, float y) { throw null; } + public static float Log(float x) { throw null; } + public static float Log(float x, float y) { throw null; } + public static float Log10(float x) { throw null; } + public static float Max(float x, float y) { throw null; } + public static float Min(float x, float y) { throw null; } + public static float Pow(float x, float y) { throw null; } + public static float Round(float x) { throw null; } + public static float Round(float x, int digits) { throw null; } + public static float Round(float x, int digits, System.MidpointRounding mode) { throw null; } + public static float Round(float x, System.MidpointRounding mode) { throw null; } + public static int Sign(float x) { throw null; } + public static float Sin(float x) { throw null; } + public static float Sinh(float x) { throw null; } + public static float Sqrt(float x) { throw null; } + public static float Tan(float x) { throw null; } + public static float Tanh(float x) { throw null; } + public static float Truncate(float x) { throw null; } + } +} diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj new file mode 100644 index 0000000000000..f6a861851a34d --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj @@ -0,0 +1,11 @@ + + + $(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum) + + + + + + + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj new file mode 100644 index 0000000000000..a7a8603ac2e73 --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -0,0 +1,25 @@ + + + $(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum) + true + $(NoWarn);CS1591 + + + Provides MathF + + true + + + + true + true + + + + + + + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx b/src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx new file mode 100644 index 0000000000000..4f074235ffe0f --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Rounding digits must be between 0 and 15, inclusive. + + + The Enum type should contain one and only one instance field. + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs new file mode 100644 index 0000000000000..6b1dec99e4d41 --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs @@ -0,0 +1,242 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +/*============================================================ +** +** Purpose: Some single-precision floating-point math operations +** +===========================================================*/ + +//This class contains only static members and doesn't require serialization. + +using System.Runtime.CompilerServices; +using System.Diagnostics.Contracts; + +namespace System +{ + public static class MathF + { + private static float singleRoundLimit = 1e8f; + + private const int maxRoundingDigits = 6; + + // This table is required for the Round function which can specify the number of digits to round to + private static float[] roundPower10Single = new float[] { + 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f + }; + + public const float PI = 3.14159265f; + + public const float E = 2.71828183f; + + private static float NegativeZero = Int32BitsToSingle(unchecked((int)0x80000000)); + + private static unsafe float Int32BitsToSingle(int value) + { + return *((float*)&value); + } + + [Pure] + private static unsafe bool IsNegative(float f) + { + return (*(uint*)(&f) & 0x80000000) == 0x80000000; + } + + public static float Abs(float x) => Math.Abs(x); + + public static float Acos(float x) => (float)Math.Acos(x); + + public static float Asin(float x) => (float)Math.Asin(x); + + public static float Atan(float x) => (float)Math.Atan(x); + + public static float Atan2(float y, float x) => (float)Math.Atan2(y, x); + + public static float Ceiling(float x) => (float)Math.Ceiling(x); + + public static float Cos(float x) => (float)Math.Cos(x); + + public static float Cosh(float x) => (float)Math.Cosh(x); + + public static float Exp(float x) => (float)Math.Exp(x); + + public static float Floor(float x) => (float)Math.Floor(x); + + public static float IEEERemainder(float x, float y) + { + if (float.IsNaN(x)) + { + return x; // IEEE 754-2008: NaN payload must be preserved + } + + if (float.IsNaN(y)) + { + return y; // IEEE 754-2008: NaN payload must be preserved + } + + var regularMod = x % y; + + if (float.IsNaN(regularMod)) + { + return float.NaN; + } + + if ((regularMod == 0) && IsNegative(x)) + { + return NegativeZero; + } + + var alternativeResult = (regularMod - (Abs(y) * Sign(x))); + + if (Abs(alternativeResult) == Abs(regularMod)) + { + var divisionResult = x / y; + var roundedResult = Round(divisionResult); + + if (Abs(roundedResult) > Abs(divisionResult)) + { + return alternativeResult; + } + else + { + return regularMod; + } + } + + if (Abs(alternativeResult) < Abs(regularMod)) + { + return alternativeResult; + } + else + { + return regularMod; + } + } + + public static float Log(float x) => (float)Math.Log(x); + + public static float Log(float x, float y) + { + if (float.IsNaN(x)) + { + return x; // IEEE 754-2008: NaN payload must be preserved + } + + if (float.IsNaN(y)) + { + return y; // IEEE 754-2008: NaN payload must be preserved + } + + if (y == 1) + { + return float.NaN; + } + + if ((x != 1) && ((y == 0) || float.IsPositiveInfinity(y))) + { + return float.NaN; + } + + return Log(x) / Log(y); + } + + public static float Log10(float x) => (float)Math.Log10(x); + + public static float Max(float x, float y) => Math.Max(x, y); + + public static float Min(float x, float y) => Math.Min(x, y); + + public static float Pow(float x, float y) => (float)Math.Pow(x, y); + + public static float Round(float x) => (float)Math.Round(x); + + public static float Round(float x, int digits) + { + if ((digits < 0) || (digits > maxRoundingDigits)) + { + throw new ArgumentOutOfRangeException(nameof(digits), SR.ArgumentOutOfRange_RoundingDigits); + } + Contract.EndContractBlock(); + + return InternalRound(x, digits, MidpointRounding.ToEven); + } + + public static float Round(float x, int digits, MidpointRounding mode) + { + if ((digits < 0) || (digits > maxRoundingDigits)) + { + throw new ArgumentOutOfRangeException(nameof(digits), SR.ArgumentOutOfRange_RoundingDigits); + } + + if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidEnum, mode, nameof(MidpointRounding)), nameof(mode)); + } + Contract.EndContractBlock(); + + return InternalRound(x, digits, mode); + } + + public static float Round(float x, MidpointRounding mode) + { + if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidEnum, mode, nameof(MidpointRounding)), nameof(mode)); + } + Contract.EndContractBlock(); + + return InternalRound(x, 0, mode); + } + + public static int Sign(float x) => Math.Sign(x); + + public static float Sin(float x) => (float)Math.Sin(x); + + public static float Sinh(float x) => (float)Math.Sinh(x); + + public static float Sqrt(float x) => (float)Math.Sqrt(x); + + public static float Tan(float x) => (float)Math.Tan(x); + + public static float Tanh(float x) => (float)Math.Tanh(x); + + public static float Truncate(float x) => InternalTruncate(x); + + private static unsafe float InternalRound(float x, int digits, MidpointRounding mode) + { + if (Abs(x) < singleRoundLimit) + { + var power10 = roundPower10Single[digits]; + + x *= power10; + + if (mode == MidpointRounding.AwayFromZero) + { + var fraction = SplitFractionSingle(&x); + + if (Abs(fraction) >= 0.5f) + { + x += Sign(fraction); + } + } + else + { + x = Round(x); + } + + x /= power10; + } + + return x; + } + + private static unsafe float InternalTruncate(float x) + { + SplitFractionSingle(&x); + return x; + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern unsafe float SplitFractionSingle(float* x); + } +} diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/strings.resx b/src/libraries/Microsoft.Bcl.Numerics/src/strings.resx new file mode 100644 index 0000000000000..46ed6f4ac81c3 --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/src/strings.resx @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Non-negative number required. + + + The number of bytes requested is too large. The number of bytes produced by SP800108HmacCounterKdf cannot exceed 536,870,911 bytes. + + + The value cannot be an empty string. + + + '{0}' is not a known hash algorithm. + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs new file mode 100644 index 0000000000000..3712ac992abbe --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs @@ -0,0 +1,1577 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +#pragma warning disable xUnit1025 // reporting duplicate test cases due to not distinguishing 0.0 from -0.0 + +namespace System.Tests +{ + public static class MathFTests + { + // binary32 (float) has a machine epsilon of 2^-23 (approx. 1.19e-07). However, this + // is slightly too accurate when writing tests meant to run against libm implementations + // for various platforms. 2^-21 (approx. 4.76e-07) seems to be as accurate as we can get. + // + // The tests themselves will take CrossPlatformMachineEpsilon and adjust it according to the expected result + // so that the delta used for comparison will compare the most significant digits and ignore + // any digits that are outside the single precision range (6-9 digits). + + // For example, a test with an expect result in the format of 0.xxxxxxxxx will use + // CrossPlatformMachineEpsilon for the variance, while an expected result in the format of 0.0xxxxxxxxx + // will use CrossPlatformMachineEpsilon / 10 and expected result in the format of x.xxxxxx will + // use CrossPlatformMachineEpsilon * 10. + private const float CrossPlatformMachineEpsilon = 4.76837158e-07f; + + // The existing estimate functions either have an error of no more than 1.5 * 2^-12 (approx. 3.66e-04) + // or perform one Newton-Raphson iteration which, for the currently tested values, gives an error of + // no more than approx. 1.5 * 2^-7 (approx 1.17e-02). + private const double CrossPlatformMachineEpsilonForEstimates = 1.171875e-02f; + + [Fact] + public static void E() + { + Assert.Equal(2.71828183f, MathF.E); + } + + [Fact] + public static void Pi() + { + Assert.Equal(3.14159265f, MathF.PI); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(-3.14159265f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // value: -(pi) expected: (pi) + [InlineData(-2.71828183f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // value: -(e) expected: (e) + [InlineData(-2.30258509f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // value: -(ln(10)) expected: (ln(10)) + [InlineData(-1.57079633f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // value: -(pi / 2) expected: (pi / 2) + [InlineData(-1.44269504f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // value: -(log2(e)) expected: (log2(e)) + [InlineData(-1.41421356f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // value: -(sqrt(2)) expected: (sqrt(2)) + [InlineData(-1.12837917f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // value: -(2 / sqrt(pi)) expected: (2 / sqrt(pi)) + [InlineData(-1.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.785398163f, 0.785398163f, CrossPlatformMachineEpsilon)] // value: -(pi / 4) expected: (pi / 4) + [InlineData(-0.707106781f, 0.707106781f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) expected: (1 / sqrt(2)) + [InlineData(-0.693147181f, 0.693147181f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) expected: (ln(2)) + [InlineData(-0.636619772f, 0.636619772f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) expected: (2 / pi) + [InlineData(-0.434294482f, 0.434294482f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) expected: (log10(e)) + [InlineData(-0.318309886f, 0.318309886f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) expected: (1 / pi) + [InlineData(-0.0f, 0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.318309886f, CrossPlatformMachineEpsilon)] // value: (1 / pi) expected: (1 / pi) + [InlineData(0.434294482f, 0.434294482f, CrossPlatformMachineEpsilon)] // value: (log10(e)) expected: (log10(e)) + [InlineData(0.636619772f, 0.636619772f, CrossPlatformMachineEpsilon)] // value: (2 / pi) expected: (2 / pi) + [InlineData(0.693147181f, 0.693147181f, CrossPlatformMachineEpsilon)] // value: (ln(2)) expected: (ln(2)) + [InlineData(0.707106781f, 0.707106781f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) expected: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.785398163f, CrossPlatformMachineEpsilon)] // value: (pi / 4) expected: (pi / 4) + [InlineData(1.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.12837917f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) expected: (2 / sqrt(pi)) + [InlineData(1.41421356f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) expected: (sqrt(2)) + [InlineData(1.44269504f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) expected: (log2(e)) + [InlineData(1.57079633f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) expected: (pi / 2) + [InlineData(2.30258509f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // value: (ln(10)) expected: (ln(10)) + [InlineData(2.71828183f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // value: (e) expected: (e) + [InlineData(3.14159265f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // value: (pi) expected: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Abs(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Abs(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: -(pi) + [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: -(e) + [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: -(sqrt(2)) + [InlineData(-1.0f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(-0.911733915f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) + [InlineData(-0.668201510f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) + [InlineData(-0.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(0.127751218f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(0.155943695f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(0.428125148f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(0.540302306f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.707106781f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4), value: (1 / sqrt(2)) + [InlineData(0.760244597f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(0.769238901f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(0.804109828f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(0.907167129f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) + [InlineData(0.949765715f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(1.0f, 0.0f, 0.0f)] + [InlineData(1.41421356f, float.NaN, 0.0f)] // value: (sqrt(2)) + [InlineData(2.71828183f, float.NaN, 0.0f)] // value: (e) + [InlineData(3.14159265f, float.NaN, 0.0f)] // value: (pi) + [InlineData(float.PositiveInfinity, float.NaN, 0.0f)] + public static void Acos(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Acos(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: -(pi) + [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: -(e) + [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: -(sqrt(2)) + [InlineData(-1.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(-0.991806244f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) + [InlineData(-0.987765946f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) + [InlineData(-0.903719457f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) + [InlineData(-0.841470985f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.743980337f, -0.839007561f, CrossPlatformMachineEpsilon)] // expected: -(pi - ln(10)) + [InlineData(-0.707106781f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4), value: (1 / sqrt(2)) + [InlineData(-0.649636939f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) + [InlineData(-0.638961276f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) + [InlineData(-0.594480769f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) + [InlineData(-0.420770483f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) + [InlineData(-0.410781291f, -0.423310825f, CrossPlatformMachineEpsilon)] // expected: -(pi - e) + [InlineData(-0.312961796f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.312961796f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(0.410781291f, 0.423310825f, CrossPlatformMachineEpsilon)] // expected: (pi - e) + [InlineData(0.420770483f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) + [InlineData(0.594480769f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(0.638961276f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(0.649636939f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(0.707106781f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4), value: (1 / sqrt(2)) + [InlineData(0.743980337f, 0.839007561f, CrossPlatformMachineEpsilon)] // expected: (pi - ln(10)) + [InlineData(0.841470985f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.903719457f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(0.987765946f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(0.991806244f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(1.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(1.41421356f, float.NaN, 0.0f)] // value: (sqrt(2)) + [InlineData(2.71828183f, float.NaN, 0.0f)] // value: (e) + [InlineData(3.14159265f, float.NaN, 0.0f)] // value: (pi) + [InlineData(float.PositiveInfinity, float.NaN, 0.0f)] + public static void Asin(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Asin(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(-7.76357567f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) + [InlineData(-6.33411917f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) + [InlineData(-2.11087684f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) + [InlineData(-1.55740772f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-1.11340715f, -0.839007561f, CrossPlatformMachineEpsilon)] // expected: -(pi - ln(10)) + [InlineData(-1.0f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) + [InlineData(-0.854510432f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) + [InlineData(-0.830640878f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) + [InlineData(-0.739302950f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) + [InlineData(-0.463829067f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) + [InlineData(-0.450549534f, -0.423310825f, CrossPlatformMachineEpsilon)] // expected: -(pi - e) + [InlineData(-0.329514733f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.329514733f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(0.450549534f, 0.423310825f, CrossPlatformMachineEpsilon)] // expected: (pi - e) + [InlineData(0.463829067f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) + [InlineData(0.739302950f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(0.830640878f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(0.854510432f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(1.0f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) + [InlineData(1.11340715f, 0.839007561f, CrossPlatformMachineEpsilon)] // expected: (pi - ln(10)) + [InlineData(1.55740772f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(2.11087684f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(6.33411917f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(7.76357567f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(float.PositiveInfinity, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + public static void Atan(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Atan(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, -1.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(float.NegativeInfinity, -0.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(float.NegativeInfinity, float.NaN, float.NaN, 0.0f)] + [InlineData(float.NegativeInfinity, 0.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(float.NegativeInfinity, 1.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(-1.0f, -1.0f, -2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: -(3 * pi / 4) + [InlineData(-1.0f, -0.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(-1.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(-1.0f, 0.0f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(-1.0f, 1.0f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) + [InlineData(-1.0f, float.PositiveInfinity, -0.0f, 0.0f)] + [InlineData(-0.991806244f, -0.127751218f, -1.69889761f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - log2(e)) + [InlineData(-0.991806244f, 0.127751218f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) + [InlineData(-0.987765946f, -0.155943695f, -1.72737909f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - sqrt(2)) + [InlineData(-0.987765946f, 0.155943695f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) + [InlineData(-0.903719457f, -0.428125148f, -2.01321349f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - (2 / sqrt(pi)) + [InlineData(-0.903719457f, 0.428125148f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi) + [InlineData(-0.841470985f, -0.540302306f, -2.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - 1) + [InlineData(-0.841470985f, 0.540302306f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.743980337f, -0.668201510f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) + [InlineData(-0.743980337f, 0.668201510f, -0.839007561f, CrossPlatformMachineEpsilon)] // expected: -(pi - ln(10)) + [InlineData(-0.707106781f, -0.707106781f, -2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: -(3 * pi / 4), y: -(1 / sqrt(2)) x: -(1 / sqrt(2)) + [InlineData(-0.707106781f, 0.707106781f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4), y: -(1 / sqrt(2)) x: (1 / sqrt(2)) + [InlineData(-0.649636939f, -0.760244597f, -2.43448587f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - (1 / sqrt(2)) + [InlineData(-0.649636939f, 0.760244597f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) + [InlineData(-0.638961276f, -0.769238901f, -2.44844547f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - ln(2)) + [InlineData(-0.638961276f, 0.769238901f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) + [InlineData(-0.594480769f, -0.804109828f, -2.50497288f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - (2 / pi)) + [InlineData(-0.594480769f, 0.804109828f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) + [InlineData(-0.420770483f, -0.907167129f, -2.70729817f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - log10(e)) + [InlineData(-0.420770483f, 0.907167129f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) + [InlineData(-0.410781291f, -0.911733915f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) + [InlineData(-0.410781291f, 0.911733915f, -0.423310825f, CrossPlatformMachineEpsilon)] // expected: -(pi - e) + [InlineData(-0.312961796f, -0.949765715f, -2.82328277f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi - (1 / pi)) + [InlineData(-0.312961796f, 0.949765715f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) + [InlineData(-0.0f, float.NegativeInfinity, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) + [InlineData(-0.0f, -1.0f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) + [InlineData(-0.0f, -0.0f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) + [InlineData(-0.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(-0.0f, 0.0f, -0.0f, 0.0f)] + [InlineData(-0.0f, 1.0f, -0.0f, 0.0f)] + [InlineData(-0.0f, float.PositiveInfinity, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(float.NaN, -1.0f, float.NaN, 0.0f)] + [InlineData(float.NaN, -0.0f, float.NaN, 0.0f)] + [InlineData(float.NaN, float.NaN, float.NaN, 0.0f)] + [InlineData(float.NaN, 0.0f, float.NaN, 0.0f)] + [InlineData(float.NaN, 1.0f, float.NaN, 0.0f)] + [InlineData(float.NaN, float.PositiveInfinity, float.NaN, 0.0f)] + [InlineData(0.0f, float.NegativeInfinity, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(0.0f, -1.0f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(0.0f, -0.0f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(0.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f, 0.0f)] + [InlineData(0.0f, 1.0f, 0.0f, 0.0f)] + [InlineData(0.0f, float.PositiveInfinity, 0.0f, 0.0f)] + [InlineData(0.312961796f, -0.949765715f, 2.82328277f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - (1 / pi)) + [InlineData(0.312961796f, 0.949765715f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(0.410781291f, -0.911733915f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) + [InlineData(0.410781291f, 0.911733915f, 0.423310825f, CrossPlatformMachineEpsilon)] // expected: (pi - e) + [InlineData(0.420770483f, -0.907167129f, 2.70729817f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - log10(e)) + [InlineData(0.420770483f, 0.907167129f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) + [InlineData(0.594480769f, -0.804109828f, 2.50497288f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - (2 / pi)) + [InlineData(0.594480769f, 0.804109828f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(0.638961276f, -0.769238901f, 2.44844547f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - ln(2)) + [InlineData(0.638961276f, 0.769238901f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(0.649636939f, -0.760244597f, 2.43448587f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - (1 / sqrt(2)) + [InlineData(0.649636939f, 0.760244597f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(0.707106781f, -0.707106781f, 2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: (3 * pi / 4), y: (1 / sqrt(2)) x: -(1 / sqrt(2)) + [InlineData(0.707106781f, 0.707106781f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4), y: (1 / sqrt(2)) x: (1 / sqrt(2)) + [InlineData(0.743980337f, -0.668201510f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) + [InlineData(0.743980337f, 0.668201510f, 0.839007561f, CrossPlatformMachineEpsilon)] // expected: (pi - ln(10)) + [InlineData(0.841470985f, -0.540302306f, 2.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - 1) + [InlineData(0.841470985f, 0.540302306f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.903719457f, -0.428125148f, 2.01321349f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - (2 / sqrt(pi)) + [InlineData(0.903719457f, 0.428125148f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(0.987765946f, -0.155943695f, 1.72737909f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - sqrt(2)) + [InlineData(0.987765946f, 0.155943695f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(0.991806244f, -0.127751218f, 1.69889761f, CrossPlatformMachineEpsilon * 10)] // expected: (pi - log2(e)) + [InlineData(0.991806244f, 0.127751218f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(1.0f, -1.0f, 2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: (3 * pi / 4) + [InlineData(1.0f, -0.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(1.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(1.0f, 0.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(1.0f, 1.0f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) + [InlineData(1.0f, float.PositiveInfinity, 0.0f, 0.0f)] + [InlineData(float.PositiveInfinity, -1.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(float.PositiveInfinity, -0.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(float.PositiveInfinity, float.NaN, float.NaN, 0.0f)] + [InlineData(float.PositiveInfinity, 0.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(float.PositiveInfinity, 1.0f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + public static void Atan2(float y, float x, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Atan2(y, x), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NegativeInfinity, -2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: -(3 * pi / 4) + [InlineData(float.NegativeInfinity, float.PositiveInfinity, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) + [InlineData(float.PositiveInfinity, float.NegativeInfinity, 2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: (3 * pi / 4 + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) + public static void Atan2_IEEE(float y, float x, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Atan2(y, x), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f)] + [InlineData(-3.14159265f, -3.0f, 0.0f)] // value: -(pi) + [InlineData(-2.71828183f, -2.0f, 0.0f)] // value: -(e) + [InlineData(-2.30258509f, -2.0f, 0.0f)] // value: -(ln(10)) + [InlineData(-1.57079633f, -1.0f, 0.0f)] // value: -(pi / 2) + [InlineData(-1.44269504f, -1.0f, 0.0f)] // value: -(log2(e)) + [InlineData(-1.41421356f, -1.0f, 0.0f)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -1.0f, 0.0f)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -1.0f, 0.0f)] + [InlineData(-0.785398163f, -0.0f, 0.0f)] // value: -(pi / 4) + [InlineData(-0.707106781f, -0.0f, 0.0f)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -0.0f, 0.0f)] // value: -(ln(2)) + [InlineData(-0.636619772f, -0.0f, 0.0f)] // value: -(2 / pi) + [InlineData(-0.434294482f, -0.0f, 0.0f)] // value: -(log10(e)) + [InlineData(-0.318309886f, -0.0f, 0.0f)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 1.0f, 0.0f)] // value: (1 / pi) + [InlineData(0.434294482f, 1.0f, 0.0f)] // value: (log10(e)) + [InlineData(0.636619772f, 1.0f, 0.0f)] // value: (2 / pi) + [InlineData(0.693147181f, 1.0f, 0.0f)] // value: (ln(2)) + [InlineData(0.707106781f, 1.0f, 0.0f)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 1.0f, 0.0f)] // value: (pi / 4) + [InlineData(1.0f, 1.0f, 0.0f)] + [InlineData(1.12837917f, 2.0f, 0.0f)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 2.0f, 0.0f)] // value: (sqrt(2)) + [InlineData(1.44269504f, 2.0f, 0.0f)] // value: (log2(e)) + [InlineData(1.57079633f, 2.0f, 0.0f)] // value: (pi / 2) + [InlineData(2.30258509f, 3.0f, 0.0f)] // value: (ln(10)) + [InlineData(2.71828183f, 3.0f, 0.0f)] // value: (e) + [InlineData(3.14159265f, 4.0f, 0.0f)] // value: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Ceiling(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Ceiling(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, -1.0f, CrossPlatformMachineEpsilon * 10)] // value: -(pi) + [InlineData(-2.71828183f, -0.911733918f, CrossPlatformMachineEpsilon)] // value: -(e) + [InlineData(-2.30258509f, -0.668201510f, CrossPlatformMachineEpsilon)] // value: -(ln(10)) + [InlineData(-1.57079633f, 0.0f, CrossPlatformMachineEpsilon)] // value: -(pi / 2) + [InlineData(-1.44269504f, 0.127751218f, CrossPlatformMachineEpsilon)] // value: -(log2(e)) + [InlineData(-1.41421356f, 0.155943695f, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, 0.428125148f, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, 0.540302306f, CrossPlatformMachineEpsilon)] + [InlineData(-0.785398163f, 0.707106781f, CrossPlatformMachineEpsilon)] // value: -(pi / 4), expected: (1 / sqrt(2)) + [InlineData(-0.707106781f, 0.760244597f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, 0.769238901f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, 0.804109828f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, 0.907167129f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, 0.949765715f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.318309886f, 0.949765715f, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.907167129f, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.804109828f, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.769238901f, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.760244597f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.707106781f, CrossPlatformMachineEpsilon)] // value: (pi / 4), expected: (1 / sqrt(2)) + [InlineData(1.0f, 0.540302306f, CrossPlatformMachineEpsilon)] + [InlineData(1.12837917f, 0.428125148f, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 0.155943695f, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) + [InlineData(1.44269504f, 0.127751218f, CrossPlatformMachineEpsilon)] // value: (log2(e)) + [InlineData(1.57079633f, 0.0f, CrossPlatformMachineEpsilon)] // value: (pi / 2) + [InlineData(2.30258509f, -0.668201510f, CrossPlatformMachineEpsilon)] // value: (ln(10)) + [InlineData(2.71828183f, -0.911733918f, CrossPlatformMachineEpsilon)] // value: (e) + [InlineData(3.14159265f, -1.0f, CrossPlatformMachineEpsilon * 10)] // value: (pi) + [InlineData(float.PositiveInfinity, float.NaN, 0.0f)] + public static void Cos(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Cos(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(-3.14159265f, 11.5919533f, CrossPlatformMachineEpsilon * 100)] // value: (pi) + [InlineData(-2.71828183f, 7.61012514f, CrossPlatformMachineEpsilon * 10)] // value: (e) + [InlineData(-2.30258509f, 5.05f, CrossPlatformMachineEpsilon * 10)] // value: (ln(10)) + [InlineData(-1.57079633f, 2.50917848f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) + [InlineData(-1.44269504f, 2.23418810f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) + [InlineData(-1.41421356f, 2.17818356f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) + [InlineData(-1.12837917f, 1.70710014f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) + [InlineData(-1.0f, 1.54308063f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.785398163f, 1.32460909f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 4) + [InlineData(-0.707106781f, 1.26059184f, CrossPlatformMachineEpsilon * 10)] // value: (1 / sqrt(2)) + [InlineData(-0.693147181f, 1.25f, CrossPlatformMachineEpsilon * 10)] // value: (ln(2)) + [InlineData(-0.636619772f, 1.20957949f, CrossPlatformMachineEpsilon * 10)] // value: (2 / pi) + [InlineData(-0.434294482f, 1.09579746f, CrossPlatformMachineEpsilon * 10)] // value: (log10(e)) + [InlineData(-0.318309886f, 1.05108979f, CrossPlatformMachineEpsilon * 10)] // value: (1 / pi) + [InlineData(-0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.318309886f, 1.05108979f, CrossPlatformMachineEpsilon * 10)] // value: (1 / pi) + [InlineData(0.434294482f, 1.09579746f, CrossPlatformMachineEpsilon * 10)] // value: (log10(e)) + [InlineData(0.636619772f, 1.20957949f, CrossPlatformMachineEpsilon * 10)] // value: (2 / pi) + [InlineData(0.693147181f, 1.25f, CrossPlatformMachineEpsilon * 10)] // value: (ln(2)) + [InlineData(0.707106781f, 1.26059184f, CrossPlatformMachineEpsilon * 10)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 1.32460909f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 4) + [InlineData(1.0f, 1.54308063f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.12837917f, 1.70710014f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 2.17818356f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) + [InlineData(1.44269504f, 2.23418810f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) + [InlineData(1.57079633f, 2.50917848f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) + [InlineData(2.30258509f, 5.05f, CrossPlatformMachineEpsilon * 10)] // value: (ln(10)) + [InlineData(2.71828183f, 7.61012514f, CrossPlatformMachineEpsilon * 10)] // value: (e) + [InlineData(3.14159265f, 11.5919533f, CrossPlatformMachineEpsilon * 100)] // value: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Cosh(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Cosh(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, 0.0f, CrossPlatformMachineEpsilon)] + [InlineData(-3.14159265f, 0.0432139183f, CrossPlatformMachineEpsilon / 10)] // value: -(pi) + [InlineData(-2.71828183f, 0.0659880358f, CrossPlatformMachineEpsilon / 10)] // value: -(e) + [InlineData(-2.30258509f, 0.1f, CrossPlatformMachineEpsilon)] // value: -(ln(10)) + [InlineData(-1.57079633f, 0.207879576f, CrossPlatformMachineEpsilon)] // value: -(pi / 2) + [InlineData(-1.44269504f, 0.236290088f, CrossPlatformMachineEpsilon)] // value: -(log2(e)) + [InlineData(-1.41421356f, 0.243116734f, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, 0.323557264f, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, 0.367879441f, CrossPlatformMachineEpsilon)] + [InlineData(-0.785398163f, 0.455938128f, CrossPlatformMachineEpsilon)] // value: -(pi / 4) + [InlineData(-0.707106781f, 0.493068691f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, 0.5f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, 0.529077808f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, 0.647721485f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, 0.727377349f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.318309886f, 1.37480223f, CrossPlatformMachineEpsilon * 10)] // value: (1 / pi) + [InlineData(0.434294482f, 1.54387344f, CrossPlatformMachineEpsilon * 10)] // value: (log10(e)) + [InlineData(0.636619772f, 1.89008116f, CrossPlatformMachineEpsilon * 10)] // value: (2 / pi) + [InlineData(0.693147181f, 2.0f, CrossPlatformMachineEpsilon * 10)] // value: (ln(2)) + [InlineData(0.707106781f, 2.02811498f, CrossPlatformMachineEpsilon * 10)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 2.19328005f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 4) + [InlineData(1.0f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) + [InlineData(1.12837917f, 3.09064302f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 4.11325038f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) + [InlineData(1.44269504f, 4.23208611f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) + [InlineData(1.57079633f, 4.81047738f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) + [InlineData(2.30258509f, 10.0f, CrossPlatformMachineEpsilon * 100)] // value: (ln(10)) + [InlineData(2.71828183f, 15.1542622f, CrossPlatformMachineEpsilon * 100)] // value: (e) + [InlineData(3.14159265f, 23.1406926f, CrossPlatformMachineEpsilon * 100)] // value: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Exp(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Exp(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f)] + [InlineData(-3.14159265f, -4.0f, 0.0f)] // value: -(pi) + [InlineData(-2.71828183f, -3.0f, 0.0f)] // value: -(e) + [InlineData(-2.30258509f, -3.0f, 0.0f)] // value: -(ln(10)) + [InlineData(-1.57079633f, -2.0f, 0.0f)] // value: -(pi / 2) + [InlineData(-1.44269504f, -2.0f, 0.0f)] // value: -(log2(e)) + [InlineData(-1.41421356f, -2.0f, 0.0f)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -2.0f, 0.0f)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -1.0f, 0.0f)] + [InlineData(-0.785398163f, -1.0f, 0.0f)] // value: -(pi / 4) + [InlineData(-0.707106781f, -1.0f, 0.0f)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -1.0f, 0.0f)] // value: -(ln(2)) + [InlineData(-0.636619772f, -1.0f, 0.0f)] // value: -(2 / pi) + [InlineData(-0.434294482f, -1.0f, 0.0f)] // value: -(log10(e)) + [InlineData(-0.318309886f, -1.0f, 0.0f)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.0f, 0.0f)] // value: (1 / pi) + [InlineData(0.434294482f, 0.0f, 0.0f)] // value: (log10(e)) + [InlineData(0.636619772f, 0.0f, 0.0f)] // value: (2 / pi) + [InlineData(0.693147181f, 0.0f, 0.0f)] // value: (ln(2)) + [InlineData(0.707106781f, 0.0f, 0.0f)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.0f, 0.0f)] // value: (pi / 4) + [InlineData(1.0f, 1.0f, 0.0f)] + [InlineData(1.12837917f, 1.0f, 0.0f)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 1.0f, 0.0f)] // value: (sqrt(2)) + [InlineData(1.44269504f, 1.0f, 0.0f)] // value: (log2(e)) + [InlineData(1.57079633f, 1.0f, 0.0f)] // value: (pi / 2) + [InlineData(2.30258509f, 2.0f, 0.0f)] // value: (ln(10)) + [InlineData(2.71828183f, 2.0f, 0.0f)] // value: (e) + [InlineData(3.14159265f, 3.0f, 0.0f)] // value: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Floor(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Floor(value), allowedVariance); + } + + [Fact] + public static void IEEERemainder() + { + Assert.Equal(-1.0f, MathF.IEEERemainder(3.0f, 2.0f)); + Assert.Equal(0.0f, MathF.IEEERemainder(4.0f, 2.0f)); + Assert.Equal(1.0f, MathF.IEEERemainder(10.0f, 3.0f)); + Assert.Equal(-1.0f, MathF.IEEERemainder(11.0f, 3.0f)); + Assert.Equal(-2.0f, MathF.IEEERemainder(28.0f, 5.0f)); + AssertExtensions.Equal(1.8f, MathF.IEEERemainder(17.8f, 4.0f), CrossPlatformMachineEpsilon * 10); + AssertExtensions.Equal(1.4f, MathF.IEEERemainder(17.8f, 4.1f), CrossPlatformMachineEpsilon * 10); + AssertExtensions.Equal(0.1000004f, MathF.IEEERemainder(-16.3f, 4.1f), CrossPlatformMachineEpsilon / 10); + AssertExtensions.Equal(1.4f, MathF.IEEERemainder(17.8f, -4.1f), CrossPlatformMachineEpsilon * 10); + AssertExtensions.Equal(-1.4f, MathF.IEEERemainder(-17.8f, -4.1f), CrossPlatformMachineEpsilon * 10); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: -(pi) + [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: -(e) + [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: -(sqrt(2)) + [InlineData(-1.0f, float.NaN, 0.0f)] + [InlineData(-0.693147181f, float.NaN, 0.0f)] // value: -(ln(2)) + [InlineData(-0.434294482f, float.NaN, 0.0f)] // value: -(log10(e)) + [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(0.0432139183f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) + [InlineData(0.0659880358f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) + [InlineData(0.1f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) + [InlineData(0.207879576f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(0.236290088f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) + [InlineData(0.243116734f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) + [InlineData(0.323557264f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) + [InlineData(0.367879441f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.455938128f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) + [InlineData(0.493068691f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) + [InlineData(0.5f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) + [InlineData(0.529077808f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) + [InlineData(0.647721485f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) + [InlineData(0.727377349f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) + [InlineData(1.0f, 0.0f, 0.0f)] + [InlineData(1.37480223f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(1.54387344f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) + [InlineData(1.89008116f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(2.0f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(2.02811498f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(2.19328005f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) + [InlineData(2.71828183f, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (e) + [InlineData(3.09064302f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(4.11325038f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(4.23208611f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(4.81047738f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(10.0f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) + [InlineData(15.1542622f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) + [InlineData(23.1406926f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Log(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Log(value), allowedVariance); + } + + [Fact] + public static void LogWithBase() + { + Assert.Equal(1.0f, MathF.Log(3.0f, 3.0f)); + AssertExtensions.Equal(2.40217350f, MathF.Log(14.0f, 3.0f), CrossPlatformMachineEpsilon * 10); + Assert.Equal(float.NegativeInfinity, MathF.Log(0.0f, 3.0f)); + Assert.Equal(float.NaN, MathF.Log(-3.0f, 3.0f)); + Assert.Equal(float.NaN, MathF.Log(float.NaN, 3.0f)); + Assert.Equal(float.PositiveInfinity, MathF.Log(float.PositiveInfinity, 3.0f)); + Assert.Equal(float.NaN, MathF.Log(float.NegativeInfinity, 3.0f)); + } + +#if NETCOREAPP2_0_OR_GREATER + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-0.113314732f, float.NaN, 0.0f)] + [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(0.113314732f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) + [InlineData(0.151955223f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) + [InlineData(0.202699566f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) + [InlineData(0.336622537f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(0.367879441f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) + [InlineData(0.375214227f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) + [InlineData(0.457429347f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) + [InlineData(0.5f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.580191810f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) + [InlineData(0.612547327f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) + [InlineData(0.618503138f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) + [InlineData(0.643218242f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) + [InlineData(0.740055574f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) + [InlineData(0.802008879f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) + [InlineData(1, 0.0f, 0.0f)] + [InlineData(1.24686899f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(1.35124987f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) + [InlineData(1.55468228f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(1.61680667f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(1.63252692f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(1.72356793f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) + [InlineData(2, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (e) + [InlineData(2.18612996f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(2.66514414f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(2.71828183f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(2.97068642f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(4.93340967f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) + [InlineData(6.58088599f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) + [InlineData(8.82497783f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Log2(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Log2(value), allowedVariance); + } + +#endif + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: -(pi) + [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: -(e) + [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: -(sqrt(2)) + [InlineData(-1.0f, float.NaN, 0.0f)] + [InlineData(-0.693147181f, float.NaN, 0.0f)] // value: -(ln(2)) + [InlineData(-0.434294482f, float.NaN, 0.0f)] // value: -(log10(e)) + [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(0.000721784159f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) + [InlineData(0.00191301410f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) + [InlineData(0.00498212830f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) + [InlineData(0.0268660410f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) + [InlineData(0.0360831928f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) + [InlineData(0.0385288847f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) + [InlineData(0.0744082059f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) + [InlineData(0.1f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.163908636f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) + [InlineData(0.196287760f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) + [InlineData(0.202699566f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) + [InlineData(0.230876765f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) + [InlineData(0.367879441f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) + [InlineData(0.480496373f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) + [InlineData(1.0f, 0.0f, 0.0f)] + [InlineData(2.08118116f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) + [InlineData(2.71828183f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) value: (e) + [InlineData(4.33131503f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) + [InlineData(4.93340967f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) + [InlineData(5.09456117f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) + [InlineData(6.10095980f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) + [InlineData(10.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(13.4393779f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) + [InlineData(25.9545535f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) + [InlineData(27.7137338f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) + [InlineData(37.2217105f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) + [InlineData(200.717432f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) + [InlineData(522.735300f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) + [InlineData(1385.45573f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Log10(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Log10(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] + [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] + [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] + [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] + [InlineData(float.NaN, float.NaN, float.NaN)] + [InlineData(float.NaN, 1.0f, float.NaN)] + [InlineData(1.0f, float.NaN, float.NaN)] + [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] + [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] + [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] + [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] + [InlineData(-0.0f, 0.0f, 0.0f)] + [InlineData(0.0f, -0.0f, 0.0f)] + [InlineData(2.0f, -3.0f, 2.0f)] + [InlineData(-3.0f, 2.0f, 2.0f)] + [InlineData(3.0f, -2.0f, 3.0f)] + [InlineData(-2.0f, 3.0f, 3.0f)] + public static void Max(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, MathF.Max(x, y), 0.0f); + + //if (float.IsNaN(x)) + //{ + // // Toggle the sign of the NaN to validate both +NaN and -NaN behave the same. + // // Negate should work as well but the JIT may constant fold or do other tricks + // // and normalize to a single NaN form so we do bitwise tricks to ensure we test + // // the right thing. + + // uint bits = BitConverter.SingleToUInt32Bits(x); + // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + // x = BitConverter.UInt32BitsToSingle(bits); + + // AssertExtensions.Equal(expectedResult, Math.Max(x, y), 0.0f); + //} + + //if (float.IsNaN(y)) + //{ + // uint bits = BitConverter.SingleToUInt32Bits(y); + // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + // y = BitConverter.UInt32BitsToSingle(bits); + + // AssertExtensions.Equal(expectedResult, Math.Max(x, y), 0.0f); + //} + } + +#if NETCOREAPP2_0_OR_GREATER + [Theory] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] + [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] + [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] + [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] + [InlineData(float.NaN, float.NaN, float.NaN)] + [InlineData(float.NaN, 1.0f, float.NaN)] + [InlineData(1.0f, float.NaN, float.NaN)] + [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] + [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] + [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] + [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] + [InlineData(-0.0f, 0.0f, 0.0f)] + [InlineData(0.0f, -0.0f, 0.0f)] + [InlineData(2.0f, -3.0f, -3.0f)] + [InlineData(-3.0f, 2.0f, -3.0f)] + [InlineData(3.0f, -2.0f, 3.0f)] + [InlineData(-2.0f, 3.0f, 3.0f)] + public static void MaxMagnitude(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, MathF.MaxMagnitude(x, y), 0.0f); + + if (float.IsNaN(x)) + { + // Toggle the sign of the NaN to validate both +NaN and -NaN behave the same. + // Negate should work as well but the JIT may constant fold or do other tricks + // and normalize to a single NaN form so we do bitwise tricks to ensure we test + // the right thing. + + uint bits = BitConverter.SingleToUInt32Bits(x); + bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + x = BitConverter.UInt32BitsToSingle(bits); + + AssertExtensions.Equal(expectedResult, Math.MaxMagnitude(x, y), 0.0f); + } + + if (float.IsNaN(y)) + { + uint bits = BitConverter.SingleToUInt32Bits(y); + bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + y = BitConverter.UInt32BitsToSingle(bits); + + AssertExtensions.Equal(expectedResult, Math.MaxMagnitude(x, y), 0.0f); + } + } + +#endif + + [Theory] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] + [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] + [InlineData(float.MinValue, float.MaxValue, float.MinValue)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue)] + [InlineData(float.NaN, float.NaN, float.NaN)] + [InlineData(float.NaN, 1.0f, float.NaN)] + [InlineData(1.0f, float.NaN, float.NaN)] + [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] + [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] + [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] + [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] + [InlineData(-0.0f, 0.0f, -0.0f)] + [InlineData(0.0f, -0.0f, -0.0f)] + [InlineData(2.0f, -3.0f, -3.0f)] + [InlineData(-3.0f, 2.0f, -3.0f)] + [InlineData(3.0f, -2.0f, -2.0f)] + [InlineData(-2.0f, 3.0f, -2.0f)] + public static void Min(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, MathF.Min(x, y), 0.0f); + + //if (float.IsNaN(x)) + //{ + // uint bits = BitConverter.SingleToUInt32Bits(x); + // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + // x = BitConverter.UInt32BitsToSingle(bits); + + // AssertExtensions.Equal(expectedResult, Math.Min(x, y), 0.0f); + //} + + //if (float.IsNaN(y)) + //{ + // uint bits = BitConverter.SingleToUInt32Bits(y); + // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + // y = BitConverter.UInt32BitsToSingle(bits); + + // AssertExtensions.Equal(expectedResult, Math.Min(x, y), 0.0f); + //} + } + +#if NETCOREAPP2_0_OR_GREATER + + [Theory] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] + [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] + [InlineData(float.MinValue, float.MaxValue, float.MinValue)] + [InlineData(float.MaxValue, float.MinValue, float.MinValue)] + [InlineData(float.NaN, float.NaN, float.NaN)] + [InlineData(float.NaN, 1.0f, float.NaN)] + [InlineData(1.0f, float.NaN, float.NaN)] + [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] + [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] + [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] + [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] + [InlineData(-0.0f, 0.0f, -0.0f)] + [InlineData(0.0f, -0.0f, -0.0f)] + [InlineData(2.0f, -3.0f, 2.0f)] + [InlineData(-3.0f, 2.0f, 2.0f)] + [InlineData(3.0f, -2.0f, -2.0f)] + [InlineData(-2.0f, 3.0f, -2.0f)] + public static void MinMagnitude(float x, float y, float expectedResult) + { + AssertExtensions.Equal(expectedResult, MathF.MinMagnitude(x, y), 0.0f); + + if (float.IsNaN(x)) + { + uint bits = BitConverter.SingleToUInt32Bits(x); + bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + x = BitConverter.UInt32BitsToSingle(bits); + + AssertExtensions.Equal(expectedResult, Math.MinMagnitude(x, y), 0.0f); + } + + if (float.IsNaN(y)) + { + uint bits = BitConverter.SingleToUInt32Bits(y); + bits ^= BitConverter.SingleToUInt32Bits(-0.0f); + y = BitConverter.UInt32BitsToSingle(bits); + + AssertExtensions.Equal(expectedResult, Math.MinMagnitude(x, y), 0.0f); + } + } +#endif + + [Theory] + [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f, 0.0f)] + [InlineData(float.NegativeInfinity, -1.0f, -0.0f, 0.0f)] + [InlineData(float.NegativeInfinity, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NegativeInfinity, float.NaN, float.NaN, 0.0f)] + [InlineData(float.NegativeInfinity, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NegativeInfinity, 1.0f, float.NegativeInfinity, 0.0f)] + [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(-10.0f, float.NegativeInfinity, 0.0f, 0.0f)] + [InlineData(-10.0f, -1.57079633f, float.NaN, 0.0f)] // y: -(pi / 2) + [InlineData(-10.0f, -1.0f, -0.1f, CrossPlatformMachineEpsilon)] + [InlineData(-10.0f, -0.785398163f, float.NaN, 0.0f)] // y: -(pi / 4) + [InlineData(-10.0f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-10.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(-10.0f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-10.0f, 0.785398163f, float.NaN, 0.0f)] // y: (pi / 4) + [InlineData(-10.0f, 1.0f, -10.0f, CrossPlatformMachineEpsilon * 100)] + [InlineData(-10.0f, 1.57079633f, float.NaN, 0.0f)] // y: (pi / 2) + [InlineData(-10.0f, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(-2.71828183f, float.NegativeInfinity, 0.0f, 0.0f)] // x: -(e) + [InlineData(-2.71828183f, -1.57079633f, float.NaN, 0.0f)] // x: -(e) y: -(pi / 2) + [InlineData(-2.71828183f, -1.0f, -0.367879441f, CrossPlatformMachineEpsilon)] // x: -(e) + [InlineData(-2.71828183f, -0.785398163f, float.NaN, 0.0f)] // x: -(e) y: -(pi / 4) + [InlineData(-2.71828183f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] // x: -(e) + [InlineData(-2.71828183f, float.NaN, float.NaN, 0.0f)] + [InlineData(-2.71828183f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] // x: -(e) + [InlineData(-2.71828183f, 0.785398163f, float.NaN, 0.0f)] // x: -(e) y: (pi / 4) + [InlineData(-2.71828183f, 1.0f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // x: -(e) expected: (e) + [InlineData(-2.71828183f, 1.57079633f, float.NaN, 0.0f)] // x: -(e) y: (pi / 2) + [InlineData(-2.71828183f, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(-1.0f, -1.0f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-1.0f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-1.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(-1.0f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-1.0f, 1.0f, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.0f, float.NegativeInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(-0.0f, -3.0f, float.NegativeInfinity, 0.0f)] + [InlineData(-0.0f, -2.0f, float.PositiveInfinity, 0.0f)] + [InlineData(-0.0f, -1.57079633f, float.PositiveInfinity, 0.0f)] // y: -(pi / 2) + [InlineData(-0.0f, -1.0f, float.NegativeInfinity, 0.0f)] + [InlineData(-0.0f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(-0.0f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.0f, 1.0f, -0.0f, 0.0f)] + [InlineData(-0.0f, 1.57079633f, 0.0f, 0.0f)] // y: -(pi / 2) + [InlineData(-0.0f, 2.0f, 0.0f, 0.0f)] + [InlineData(-0.0f, 3.0f, -0.0f, 0.0f)] + [InlineData(-0.0f, float.PositiveInfinity, 0.0f, 0.0f)] + [InlineData(float.NaN, float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(float.NaN, -1.0f, float.NaN, 0.0f)] + [InlineData(float.NaN, float.NaN, float.NaN, 0.0f)] + [InlineData(float.NaN, 1.0f, float.NaN, 0.0f)] + [InlineData(float.NaN, float.PositiveInfinity, float.NaN, 0.0f)] + [InlineData(0.0f, float.NegativeInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(0.0f, -3.0f, float.PositiveInfinity, 0.0f)] + [InlineData(0.0f, -2.0f, float.PositiveInfinity, 0.0f)] + [InlineData(0.0f, -1.57079633f, float.PositiveInfinity, 0.0f)] // y: -(pi / 2) + [InlineData(0.0f, -1.0f, float.PositiveInfinity, 0.0f)] + [InlineData(0.0f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.0f, 1.0f, 0.0f, 0.0f)] + [InlineData(0.0f, 1.57079633f, 0.0f, 0.0f)] // y: -(pi / 2) + [InlineData(0.0f, 2.0f, 0.0f, 0.0f)] + [InlineData(0.0f, 3.0f, 0.0f, 0.0f)] + [InlineData(0.0f, float.PositiveInfinity, 0.0f, 0.0f)] + [InlineData(1.0f, float.NegativeInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0f, -1.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0f, 1.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0f, float.PositiveInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(2.71828183f, float.NegativeInfinity, 0.0f, 0.0f)] + [InlineData(2.71828183f, -3.14159265f, 0.0432139183f, CrossPlatformMachineEpsilon / 10)] // x: (e) y: -(pi) + [InlineData(2.71828183f, -2.71828183f, 0.0659880358f, CrossPlatformMachineEpsilon / 10)] // x: (e) y: -(e) + [InlineData(2.71828183f, -2.30258509f, 0.1f, CrossPlatformMachineEpsilon)] // x: (e) y: -(ln(10)) + [InlineData(2.71828183f, -1.57079633f, 0.207879576f, CrossPlatformMachineEpsilon)] // x: (e) y: -(pi / 2) + [InlineData(2.71828183f, -1.44269504f, 0.236290088f, CrossPlatformMachineEpsilon)] // x: (e) y: -(log2(e)) + [InlineData(2.71828183f, -1.41421356f, 0.243116734f, CrossPlatformMachineEpsilon)] // x: (e) y: -(sqrt(2)) + [InlineData(2.71828183f, -1.12837917f, 0.323557264f, CrossPlatformMachineEpsilon)] // x: (e) y: -(2 / sqrt(pi)) + [InlineData(2.71828183f, -1.0f, 0.367879441f, CrossPlatformMachineEpsilon)] // x: (e) + [InlineData(2.71828183f, -0.785398163f, 0.455938128f, CrossPlatformMachineEpsilon)] // x: (e) y: -(pi / 4) + [InlineData(2.71828183f, -0.707106781f, 0.493068691f, CrossPlatformMachineEpsilon)] // x: (e) y: -(1 / sqrt(2)) + [InlineData(2.71828183f, -0.693147181f, 0.5f, CrossPlatformMachineEpsilon)] // x: (e) y: -(ln(2)) + [InlineData(2.71828183f, -0.636619772f, 0.529077808f, CrossPlatformMachineEpsilon)] // x: (e) y: -(2 / pi) + [InlineData(2.71828183f, -0.434294482f, 0.647721485f, CrossPlatformMachineEpsilon)] // x: (e) y: -(log10(e)) + [InlineData(2.71828183f, -0.318309886f, 0.727377349f, CrossPlatformMachineEpsilon)] // x: (e) y: -(1 / pi) + [InlineData(2.71828183f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] // x: (e) + [InlineData(2.71828183f, float.NaN, float.NaN, 0.0f)] + [InlineData(2.71828183f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] // x: (e) + [InlineData(2.71828183f, 0.318309886f, 1.37480223f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (1 / pi) + [InlineData(2.71828183f, 0.434294482f, 1.54387344f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (log10(e)) + [InlineData(2.71828183f, 0.636619772f, 1.89008116f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (2 / pi) + [InlineData(2.71828183f, 0.693147181f, 2.0f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (ln(2)) + [InlineData(2.71828183f, 0.707106781f, 2.02811498f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (1 / sqrt(2)) + [InlineData(2.71828183f, 0.785398163f, 2.19328005f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi / 4) + [InlineData(2.71828183f, 1.0f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // x: (e) expected: (e) + [InlineData(2.71828183f, 1.12837917f, 3.09064302f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (2 / sqrt(pi)) + [InlineData(2.71828183f, 1.41421356f, 4.11325038f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (sqrt(2)) + [InlineData(2.71828183f, 1.44269504f, 4.23208611f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (log2(e)) + [InlineData(2.71828183f, 1.57079633f, 4.81047738f, CrossPlatformMachineEpsilon * 10)] // x: (e) y: (pi / 2) + [InlineData(2.71828183f, 2.30258509f, 10.0f, CrossPlatformMachineEpsilon * 100)] // x: (e) y: (ln(10)) + [InlineData(2.71828183f, 2.71828183f, 15.1542622f, CrossPlatformMachineEpsilon * 100)] // x: (e) y: (e) + [InlineData(2.71828183f, 3.14159265f, 23.1406926f, CrossPlatformMachineEpsilon * 100)] // x: (e) y: (pi) + [InlineData(2.71828183f, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] // x: (e) + [InlineData(10.0f, float.NegativeInfinity, 0.0f, 0.0f)] + [InlineData(10.0f, -3.14159265f, 0.000721784159f, CrossPlatformMachineEpsilon / 1000)] // y: -(pi) + [InlineData(10.0f, -2.71828183f, 0.00191301410f, CrossPlatformMachineEpsilon / 100)] // y: -(e) + [InlineData(10.0f, -2.30258509f, 0.00498212830f, CrossPlatformMachineEpsilon / 100)] // y: -(ln(10)) + [InlineData(10.0f, -1.57079633f, 0.0268660410f, CrossPlatformMachineEpsilon / 10)] // y: -(pi / 2) + [InlineData(10.0f, -1.44269504f, 0.0360831928f, CrossPlatformMachineEpsilon / 10)] // y: -(log2(e)) + [InlineData(10.0f, -1.41421356f, 0.0385288847f, CrossPlatformMachineEpsilon / 10)] // y: -(sqrt(2)) + [InlineData(10.0f, -1.12837917f, 0.0744082059f, CrossPlatformMachineEpsilon / 10)] // y: -(2 / sqrt(pi)) + [InlineData(10.0f, -1.0f, 0.1f, CrossPlatformMachineEpsilon)] + [InlineData(10.0f, -0.785398163f, 0.163908636f, CrossPlatformMachineEpsilon)] // y: -(pi / 4) + [InlineData(10.0f, -0.707106781f, 0.196287760f, CrossPlatformMachineEpsilon)] // y: -(1 / sqrt(2)) + [InlineData(10.0f, -0.693147181f, 0.202699566f, CrossPlatformMachineEpsilon)] // y: -(ln(2)) + [InlineData(10.0f, -0.636619772f, 0.230876765f, CrossPlatformMachineEpsilon)] // y: -(2 / pi) + [InlineData(10.0f, -0.434294482f, 0.367879441f, CrossPlatformMachineEpsilon)] // y: -(log10(e)) + [InlineData(10.0f, -0.318309886f, 0.480496373f, CrossPlatformMachineEpsilon)] // y: -(1 / pi) + [InlineData(10.0f, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(10.0f, float.NaN, float.NaN, 0.0f)] + [InlineData(10.0f, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(10.0f, 0.318309886f, 2.08118116f, CrossPlatformMachineEpsilon * 10)] // y: (1 / pi) + [InlineData(10.0f, 0.434294482f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // y: (log10(e)) expected: (e) + [InlineData(10.0f, 0.636619772f, 4.33131503f, CrossPlatformMachineEpsilon * 10)] // y: (2 / pi) + [InlineData(10.0f, 0.693147181f, 4.93340967f, CrossPlatformMachineEpsilon * 10)] // y: (ln(2)) + [InlineData(10.0f, 0.707106781f, 5.09456117f, CrossPlatformMachineEpsilon * 10)] // y: (1 / sqrt(2)) + [InlineData(10.0f, 0.785398163f, 6.10095980f, CrossPlatformMachineEpsilon * 10)] // y: (pi / 4) + [InlineData(10.0f, 1.0f, 10.0f, CrossPlatformMachineEpsilon * 100)] + [InlineData(10.0f, 1.12837917f, 13.4393779f, CrossPlatformMachineEpsilon * 100)] // y: (2 / sqrt(pi)) + [InlineData(10.0f, 1.41421356f, 25.9545535f, CrossPlatformMachineEpsilon * 100)] // y: (sqrt(2)) + [InlineData(10.0f, 1.44269504f, 27.7137338f, CrossPlatformMachineEpsilon * 100)] // y: (log2(e)) + [InlineData(10.0f, 1.57079633f, 37.2217105f, CrossPlatformMachineEpsilon * 100)] // y: (pi / 2) + [InlineData(10.0f, 2.30258509f, 200.717432f, CrossPlatformMachineEpsilon * 1000)] // y: (ln(10)) + [InlineData(10.0f, 2.71828183f, 522.735300f, CrossPlatformMachineEpsilon * 1000)] // y: (e) + [InlineData(10.0f, 3.14159265f, 1385.45573f, CrossPlatformMachineEpsilon * 10000)] // y: (pi) + [InlineData(10.0f, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + [InlineData(float.PositiveInfinity, float.NegativeInfinity, 0.0f, 0.0f)] + [InlineData(float.PositiveInfinity, -1.0f, 0.0f, 0.0f)] + [InlineData(float.PositiveInfinity, -0.0f, 1.0f, 0.0f)] + [InlineData(float.PositiveInfinity, float.NaN, float.NaN, 0.0f)] + [InlineData(float.PositiveInfinity, 0.0f, 1.0f, 0.0f)] + [InlineData(float.PositiveInfinity, 1.0f, float.PositiveInfinity, 0.0f)] + [InlineData(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Pow(float x, float y, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Pow(x, y), allowedVariance); + } + + [Theory] + [InlineData(-1.0f, float.NegativeInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-1.0f, float.PositiveInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NaN, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NaN, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0f, float.NaN, 1.0f, CrossPlatformMachineEpsilon * 10)] + public static void Pow_IEEE(float x, float y, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Pow(x, y), allowedVariance); + } + +#if NETCOREAPP2_0_OR_GREATER + + [Theory] + [InlineData(float.NegativeInfinity, -0.0f, 0.0f)] + [InlineData(-3.14159265f, -0.318309873f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi) + [InlineData(-2.71828183f, -0.36787945f, CrossPlatformMachineEpsilonForEstimates)] // value: (e) + [InlineData(-2.30258509f, -0.434294462f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(10)) + [InlineData(-1.57079633f, -0.636619747f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 2) + [InlineData(-1.44269504f, -0.693147182f, CrossPlatformMachineEpsilonForEstimates)] // value: (log2(e)) + [InlineData(-1.41421356f, -0.707106769f, CrossPlatformMachineEpsilonForEstimates)] // value: (sqrt(2)) + [InlineData(-1.12837917f, -0.886226892f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / sqrt(pi)) + [InlineData(-1.0f, -1.0f, CrossPlatformMachineEpsilonForEstimates)] + [InlineData(-0.785398163f, -1.27323949f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 4) + [InlineData(-0.707106781f, -1.41421354f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / sqrt(2)) + [InlineData(-0.693147181f, -1.44269502f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(2)) + [InlineData(-0.636619772f, -1.57079637f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / pi) + [InlineData(-0.434294482f, -2.30258512f, CrossPlatformMachineEpsilonForEstimates)] // value: (log10(e)) + [InlineData(-0.318309886f, -3.14159274f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / pi) + [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, float.PositiveInfinity, 0.0f)] + [InlineData(0.318309886f, 3.14159274f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / pi) + [InlineData(0.434294482f, 2.30258512f, CrossPlatformMachineEpsilonForEstimates)] // value: (log10(e)) + [InlineData(0.636619772f, 1.57079637f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / pi) + [InlineData(0.693147181f, 1.44269502f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(2)) + [InlineData(0.707106781f, 1.41421354f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 1.27323949f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 4) + [InlineData(1.0f, 1.0f, CrossPlatformMachineEpsilonForEstimates)] + [InlineData(1.12837917f, 0.886226892f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 0.707106769f, CrossPlatformMachineEpsilonForEstimates)] // value: (sqrt(2)) + [InlineData(1.44269504f, 0.693147182f, CrossPlatformMachineEpsilonForEstimates)] // value: (log2(e)) + [InlineData(1.57079633f, 0.636619747f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 2) + [InlineData(2.30258509f, 0.434294462f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(10)) + [InlineData(2.71828183f, 0.36787945f, CrossPlatformMachineEpsilonForEstimates)] // value: (e) + [InlineData(3.14159265f, 0.318309873f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi) + [InlineData(float.PositiveInfinity, 0.0f, 0.0f)] + public static void ReciprocalEstimate(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.ReciprocalEstimate(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: (pi) + [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: (e) + [InlineData(-2.30258509f, float.NaN, 0.0f)] // value: (ln(10)) + [InlineData(-1.57079633f, float.NaN, 0.0f)] // value: (pi / 2) + [InlineData(-1.44269504f, float.NaN, 0.0f)] // value: (log2(e)) + [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: (sqrt(2)) + [InlineData(-1.12837917f, float.NaN, 0.0f)] // value: (2 / sqrt(pi)) + [InlineData(-1.0f, float.NaN, 0.0f)] + [InlineData(-0.785398163f, float.NaN, 0.0f)] // value: (pi / 4) + [InlineData(-0.707106781f, float.NaN, 0.0f)] // value: (1 / sqrt(2)) + [InlineData(-0.693147181f, float.NaN, 0.0f)] // value: (ln(2)) + [InlineData(-0.636619772f, float.NaN, 0.0f)] // value: (2 / pi) + [InlineData(-0.434294482f, float.NaN, 0.0f)] // value: (log10(e)) + [InlineData(-0.318309886f, float.NaN, 0.0f)] // value: (1 / pi) + [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, float.PositiveInfinity, 0.0f)] + [InlineData(0.318309886f, 1.7724539f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / pi) + [InlineData(0.434294482f, 1.51742709f, CrossPlatformMachineEpsilonForEstimates)] // value: (log10(e)) + [InlineData(0.636619772f, 1.25331414f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / pi) + [InlineData(0.693147181f, 1.2011224f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(2)) + [InlineData(0.707106781f, 1.18920708f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 1.12837911f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 4) + [InlineData(1.0f, 1.0f, CrossPlatformMachineEpsilonForEstimates)] + [InlineData(1.12837917f, 0.941396296f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 0.840896428f, CrossPlatformMachineEpsilonForEstimates)] // value: (sqrt(2)) + [InlineData(1.44269504f, 0.832554638f, CrossPlatformMachineEpsilonForEstimates)] // value: (log2(e)) + [InlineData(1.57079633f, 0.797884583f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 2) + [InlineData(2.30258509f, 0.659010231f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(10)) + [InlineData(2.71828183f, 0.606530666f, CrossPlatformMachineEpsilonForEstimates)] // value: (e) + [InlineData(3.14159265f, 0.564189553f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi) + [InlineData(float.PositiveInfinity, 0.0f, 0.0f)] + public static void ReciprocalSqrtEstimate(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.ReciprocalSqrtEstimate(value), allowedVariance); + } + +#endif + + public static IEnumerable Round_Digits_TestData + { + get + { + yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToEven }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToEven }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToEven }; + yield return new object[] { 0, 0, 3, MidpointRounding.ToEven }; + yield return new object[] { 3.42156f, 3.422f, 3, MidpointRounding.ToEven }; + yield return new object[] { -3.42156f, -3.422f, 3, MidpointRounding.ToEven }; + + yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.AwayFromZero }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.AwayFromZero }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.AwayFromZero }; + yield return new object[] { 0, 0, 3, MidpointRounding.AwayFromZero }; + yield return new object[] { 3.42156f, 3.422f, 3, MidpointRounding.AwayFromZero }; + yield return new object[] { -3.42156f, -3.422f, 3, MidpointRounding.AwayFromZero }; +#if NETCOREAPP2_0_OR_GREATER + + yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToZero }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToZero }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToZero }; + yield return new object[] { 0, 0, 3, MidpointRounding.ToZero }; + yield return new object[] { 3.42156f, 3.421f, 3, MidpointRounding.ToZero }; + yield return new object[] { -3.42156f, -3.421f, 3, MidpointRounding.ToZero }; + + yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToNegativeInfinity }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToNegativeInfinity }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToNegativeInfinity }; + yield return new object[] { 0, 0, 3, MidpointRounding.ToNegativeInfinity }; + yield return new object[] { 3.42156f, 3.421f, 3, MidpointRounding.ToNegativeInfinity }; + yield return new object[] { -3.42156f, -3.422f, 3, MidpointRounding.ToNegativeInfinity }; + + yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToPositiveInfinity }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToPositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToPositiveInfinity }; + yield return new object[] { 0, 0, 3, MidpointRounding.ToPositiveInfinity }; + yield return new object[] { 3.42156f, 3.422f, 3, MidpointRounding.ToPositiveInfinity }; + yield return new object[] { -3.42156f, -3.421f, 3, MidpointRounding.ToPositiveInfinity }; +#endif + } + } + + [Fact] + public static void Round() + { + Assert.Equal(0.0f, MathF.Round(0.0f)); + Assert.Equal(1.0f, MathF.Round(1.4f)); + Assert.Equal(2.0f, MathF.Round(1.5f)); + Assert.Equal(2e7f, MathF.Round(2e7f)); + Assert.Equal(0.0f, MathF.Round(-0.0f)); + Assert.Equal(-1.0f, MathF.Round(-1.4f)); + Assert.Equal(-2.0f, MathF.Round(-1.5f)); + Assert.Equal(-2e7f, MathF.Round(-2e7f)); + } + + [Theory] + [InlineData(MidpointRounding.ToEven)] + [InlineData(MidpointRounding.AwayFromZero)] +#if NETCOREAPP2_0_OR_GREATER + [InlineData(MidpointRounding.ToNegativeInfinity)] + [InlineData(MidpointRounding.ToPositiveInfinity)] +#endif + public static void Round_Digits_ByMidpointRounding(MidpointRounding mode) + { + Assert.Equal(float.PositiveInfinity, MathF.Round(float.PositiveInfinity, 3, mode)); + Assert.Equal(float.NegativeInfinity, MathF.Round(float.NegativeInfinity, 3, mode)); + } + + [Theory] + [MemberData(nameof(Round_Digits_TestData))] + public static void Round_Digits(float x, float expected, int digits, MidpointRounding mode) + { + AssertExtensions.Equal(expected, MathF.Round(x, digits, mode), CrossPlatformMachineEpsilon * 10); + } + +#if NETCOREAPP2_0_OR_GREATER + + [Theory] + [InlineData(float.NegativeInfinity, unchecked((int)(0x7FFFFFFF)), float.NegativeInfinity, 0)] + [InlineData(float.PositiveInfinity, unchecked((int)(0x7FFFFFFF)), float.PositiveInfinity, 0)] + [InlineData(float.NaN, 0, float.NaN, 0)] + [InlineData(float.NaN, 0, float.NaN, 0)] + [InlineData(float.PositiveInfinity, 0, float.PositiveInfinity, 0)] + [InlineData(float.NaN, 0, float.NaN, 0)] + [InlineData(float.NaN, 1, float.NaN, 0)] + [InlineData(float.PositiveInfinity, 2147483647, float.PositiveInfinity, 0)] + [InlineData(float.PositiveInfinity, -2147483647, float.PositiveInfinity, 0)] + [InlineData(float.NaN, 2147483647, float.NaN, 0)] + [InlineData(-0.0f, unchecked((int)(0x80000000)), -0.0f, 0)] + [InlineData(float.NaN, unchecked((int)(0x7FFFFFFF)), float.NaN, 0)] + [InlineData(0, unchecked((int)(0x80000000)), 0, 0)] + [InlineData(0.113314732f, -4, 0.00708217081f, CrossPlatformMachineEpsilon / 100)] + [InlineData(-0.113314732f, -3, -0.0141643415f, CrossPlatformMachineEpsilon / 10)] + [InlineData(0.151955223f, -3, 0.0189944021f, CrossPlatformMachineEpsilon / 10)] + [InlineData(0.202699566f, -3, 0.0253374465f, CrossPlatformMachineEpsilon / 10)] + [InlineData(0.336622537f, -2, 0.084155634f, CrossPlatformMachineEpsilon / 10)] + [InlineData(0.367879441f, -2, 0.0919698626f, CrossPlatformMachineEpsilon / 10)] + [InlineData(0.375214227f, -2, 0.0938035548f, CrossPlatformMachineEpsilon / 10)] + [InlineData(0.457429347f, -2, 0.114357337f, CrossPlatformMachineEpsilon)] + [InlineData(0.5f, -1, 0.25f, CrossPlatformMachineEpsilon)] + [InlineData(0.580191810f, -1, 0.290095896f, CrossPlatformMachineEpsilon)] + [InlineData(0.612547327f, -1, 0.306273669f, CrossPlatformMachineEpsilon)] + [InlineData(0.618503138f, -1, 0.309251577f, CrossPlatformMachineEpsilon)] + [InlineData(0.643218242f, -1, 0.321609110f, CrossPlatformMachineEpsilon)] + [InlineData(0.740055574f, -1, 0.370027781f, CrossPlatformMachineEpsilon)] + [InlineData(0.802008879f, -1, 0.401004434f, CrossPlatformMachineEpsilon)] + [InlineData(0, 2147483647, 0, CrossPlatformMachineEpsilon)] + [InlineData(0, -2147483647, 0, CrossPlatformMachineEpsilon)] + [InlineData(0, 2147483647, 0, CrossPlatformMachineEpsilon)] + [InlineData(1, -1, 0.5, CrossPlatformMachineEpsilon)] + [InlineData(1, 0, 1, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.24686899f, 0, 1.24686899f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.35124987f, 0, 1.35124987f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.55468228f, 0, 1.55468228f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.61680667f, 0, 1.61680667f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.63252692f, 0, 1.63252692f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.72356793f, 0, 1.72356793f, CrossPlatformMachineEpsilon * 10)] + [InlineData(2, 1, 4, CrossPlatformMachineEpsilon * 10)] + [InlineData(2.18612996f, 1, 4.37225992f, CrossPlatformMachineEpsilon * 10)] + [InlineData(2.66514414f, 1, 5.33028829f, CrossPlatformMachineEpsilon * 10)] + [InlineData(2.71828183f, 1, 5.43656366f, CrossPlatformMachineEpsilon * 10)] + [InlineData(2.97068642f, 1, 5.94137285f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1, 0, 1, CrossPlatformMachineEpsilon * 10)] + [InlineData(1, 1, 2, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.7014118E+38, -276, 1E-45, CrossPlatformMachineEpsilon * 10)] + [InlineData(1E-45, 276, 1.7014118E+38, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.0002441, -149, 1E-45, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.74999994, -148, 1E-45, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.50000066, -128, 1.46937E-39, CrossPlatformMachineEpsilon * 10)] + [InlineData(-8.066849, -2, -2.0167122, CrossPlatformMachineEpsilon * 10)] + [InlineData(4.3452396, -1, 2.1726198, CrossPlatformMachineEpsilon * 10)] + [InlineData(-8.3814335, 0, -8.3814335, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.6619859, 3, 5.295887, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.40660393, 4, -6.505663, CrossPlatformMachineEpsilon * 10)] + [InlineData(-6.5316734, 1, -13.063347, CrossPlatformMachineEpsilon * 100)] + [InlineData(9.267057, 2, 37.06823, CrossPlatformMachineEpsilon * 100)] + [InlineData(0.56175977, 5, 17.976313, CrossPlatformMachineEpsilon * 100)] + [InlineData(0.7741523, 6, 49.545746, CrossPlatformMachineEpsilon * 100)] + [InlineData(-0.6787637, 7, -86.88175, CrossPlatformMachineEpsilon * 100)] + [InlineData(4.93340967f, 2, 19.7336387f, CrossPlatformMachineEpsilon * 100)] + [InlineData(6.58088599f, 2, 26.3235440f, CrossPlatformMachineEpsilon * 100)] + [InlineData(8.82497783f, 3, 70.5998226f, CrossPlatformMachineEpsilon * 100)] + public static void ScaleB(float x, int n, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.ScaleB(x, n), allowedVariance); + } + +#endif + + [Fact] + public static void Sign() + { + Assert.Equal(0, MathF.Sign(0.0f)); + Assert.Equal(0, MathF.Sign(-0.0f)); + Assert.Equal(-1, MathF.Sign(-3.14f)); + Assert.Equal(1, MathF.Sign(3.14f)); + Assert.Equal(-1, MathF.Sign(float.NegativeInfinity)); + Assert.Equal(1, MathF.Sign(float.PositiveInfinity)); + Assert.Throws(() => MathF.Sign(float.NaN)); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, -0.0f, CrossPlatformMachineEpsilon)] // value: -(pi) + [InlineData(-2.71828183f, -0.410781291f, CrossPlatformMachineEpsilon)] // value: -(e) + [InlineData(-2.30258509f, -0.743980337f, CrossPlatformMachineEpsilon)] // value: -(ln(10)) + [InlineData(-1.57079633f, -1.0f, CrossPlatformMachineEpsilon * 10)] // value: -(pi / 2) + [InlineData(-1.44269504f, -0.991806244f, CrossPlatformMachineEpsilon)] // value: -(log2(e)) + [InlineData(-1.41421356f, -0.987765946f, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -0.903719457f, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -0.841470985f, CrossPlatformMachineEpsilon)] + [InlineData(-0.785398163f, -0.707106781f, CrossPlatformMachineEpsilon)] // value: -(pi / 4), expected: -(1 / sqrt(2)) + [InlineData(-0.707106781f, -0.649636939f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -0.638961276f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, -0.594480769f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, -0.420770483f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, -0.312961796f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.312961796f, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.420770483f, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.594480769f, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.638961276f, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.649636939f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.707106781f, CrossPlatformMachineEpsilon)] // value: (pi / 4), expected: (1 / sqrt(2)) + [InlineData(1.0f, 0.841470985f, CrossPlatformMachineEpsilon)] + [InlineData(1.12837917f, 0.903719457f, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 0.987765946f, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) + [InlineData(1.44269504f, 0.991806244f, CrossPlatformMachineEpsilon)] // value: (log2(e)) + [InlineData(1.57079633f, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) + [InlineData(2.30258509f, 0.743980337f, CrossPlatformMachineEpsilon)] // value: (ln(10)) + [InlineData(2.71828183f, 0.410781291f, CrossPlatformMachineEpsilon)] // value: (e) + [InlineData(3.14159265f, 0.0f, CrossPlatformMachineEpsilon)] // value: (pi) + [InlineData(float.PositiveInfinity, float.NaN, 0.0f)] + public static void Sin(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Sin(value), allowedVariance); + } + +#if NETCOREAPP2_0_OR_GREATER + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, float.NaN, 0.0f, 0.0f)] + [InlineData(-3.14159265f, -0.0f, -1.0f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon * 10)] // value: -(pi) + [InlineData(-2.71828183f, -0.410781291f, -0.911733918f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(e) + [InlineData(-2.30258509f, -0.743980337f, -0.668201510f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(ln(10)) + [InlineData(-1.57079633f, -1.0f, 0.0f, CrossPlatformMachineEpsilon * 10, CrossPlatformMachineEpsilon)] // value: -(pi / 2) + [InlineData(-1.44269504f, -0.991806244f, 0.127751218f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(log2(e)) + [InlineData(-1.41421356f, -0.987765946f, 0.155943695f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -0.903719457f, 0.428125148f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -0.841470985f, 0.540302306f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] + [InlineData(-0.785398163f, -0.707106781f, 0.707106781f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(pi / 4), expected_sin: -(1 / sqrt(2)), expected_cos: 1 + [InlineData(-0.707106781f, -0.649636939f, 0.760244597f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -0.638961276f, 0.769238901f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, -0.594480769f, 0.804109828f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, -0.420770483f, 0.907167129f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, -0.312961796f, 0.949765715f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 1.0f, 0.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(float.NaN, float.NaN, float.NaN, 0.0f, 0.0f)] + [InlineData(0.0f, 0.0f, 1.0f, 0.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(0.318309886f, 0.312961796f, 0.949765715f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.420770483f, 0.907167129f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.594480769f, 0.804109828f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.638961276f, 0.769238901f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.649636939f, 0.760244597f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.707106781f, 0.707106781f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (pi / 4), expected_sin: (1 / sqrt(2)), expected_cos: 1 + [InlineData(1.0f, 0.841470985f, 0.540302306f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] + [InlineData(1.12837917f, 0.903719457f, 0.428125148f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 0.987765946f, 0.155943695f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) + [InlineData(1.44269504f, 0.991806244f, 0.127751218f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (log2(e)) + [InlineData(1.57079633f, 1.0f, 0.0f, CrossPlatformMachineEpsilon * 10, CrossPlatformMachineEpsilon)] // value: (pi / 2) + [InlineData(2.30258509f, 0.743980337f, -0.668201510f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (ln(10)) + [InlineData(2.71828183f, 0.410781291f, -0.911733918f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (e) + [InlineData(3.14159265f, 0.0f, -1.0f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon * 10)] // value: (pi) + [InlineData(float.PositiveInfinity, float.NaN, float.NaN, 0.0f, 0.0f)] + public static void SinCos(float value, float expectedResultSin, float expectedResultCos, float allowedVarianceSin, float allowedVarianceCos) + { + (float resultSin, float resultCos) = MathF.SinCos(value); + AssertExtensions.Equal(expectedResultSin, resultSin, allowedVarianceSin); + AssertExtensions.Equal(expectedResultCos, resultCos, allowedVarianceCos); + } + +#endif + + [Theory] + [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f)] + [InlineData(-3.14159265f, -11.5487394f, CrossPlatformMachineEpsilon * 100)] // value: -(pi) + [InlineData(-2.71828183f, -7.54413710f, CrossPlatformMachineEpsilon * 10)] // value: -(e) + [InlineData(-2.30258509f, -4.95f, CrossPlatformMachineEpsilon * 10)] // value: -(ln(10)) + [InlineData(-1.57079633f, -2.30129890f, CrossPlatformMachineEpsilon * 10)] // value: -(pi / 2) + [InlineData(-1.44269504f, -1.99789801f, CrossPlatformMachineEpsilon * 10)] // value: -(log2(e)) + [InlineData(-1.41421356f, -1.93506682f, CrossPlatformMachineEpsilon * 10)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -1.38354288f, CrossPlatformMachineEpsilon * 10)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -1.17520119f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.785398163f, -0.868670961f, CrossPlatformMachineEpsilon)] // value: -(pi / 4) + [InlineData(-0.707106781f, -0.767523145f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -0.75f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, -0.680501678f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, -0.448075979f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, -0.323712439f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.323712439f, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.448075979f, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.680501678f, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.75f, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.767523145f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.868670961f, CrossPlatformMachineEpsilon)] // value: (pi / 4) + [InlineData(1.0f, 1.17520119f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.12837917f, 1.38354288f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 1.93506682f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) + [InlineData(1.44269504f, 1.99789801f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) + [InlineData(1.57079633f, 2.30129890f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) + [InlineData(2.30258509f, 4.95f, CrossPlatformMachineEpsilon * 10)] // value: (ln(10)) + [InlineData(2.71828183f, 7.54413710f, CrossPlatformMachineEpsilon * 10)] // value: (e) + [InlineData(3.14159265f, 11.5487394f, CrossPlatformMachineEpsilon * 100)] // value: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Sinh(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Sinh(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: (pi) + [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: (e) + [InlineData(-2.30258509f, float.NaN, 0.0f)] // value: (ln(10)) + [InlineData(-1.57079633f, float.NaN, 0.0f)] // value: (pi / 2) + [InlineData(-1.44269504f, float.NaN, 0.0f)] // value: (log2(e)) + [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: (sqrt(2)) + [InlineData(-1.12837917f, float.NaN, 0.0f)] // value: (2 / sqrt(pi)) + [InlineData(-1.0f, float.NaN, 0.0f)] + [InlineData(-0.785398163f, float.NaN, 0.0f)] // value: (pi / 4) + [InlineData(-0.707106781f, float.NaN, 0.0f)] // value: (1 / sqrt(2)) + [InlineData(-0.693147181f, float.NaN, 0.0f)] // value: (ln(2)) + [InlineData(-0.636619772f, float.NaN, 0.0f)] // value: (2 / pi) + [InlineData(-0.434294482f, float.NaN, 0.0f)] // value: (log10(e)) + [InlineData(-0.318309886f, float.NaN, 0.0f)] // value: (1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.564189584f, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.659010229f, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.797884561f, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.832554611f, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.840896415f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.886226925f, CrossPlatformMachineEpsilon)] // value: (pi / 4) + [InlineData(1.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.12837917f, 1.06225193f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 1.18920712f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) + [InlineData(1.44269504f, 1.20112241f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) + [InlineData(1.57079633f, 1.25331414f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 2) + [InlineData(2.30258509f, 1.51742713f, CrossPlatformMachineEpsilon * 10)] // value: (ln(10)) + [InlineData(2.71828183f, 1.64872127f, CrossPlatformMachineEpsilon * 10)] // value: (e) + [InlineData(3.14159265f, 1.77245385F, CrossPlatformMachineEpsilon * 10)] // value: (pi) + [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] + public static void Sqrt(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Sqrt(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] + [InlineData(-3.14159265f, -0.0f, CrossPlatformMachineEpsilon)] // value: -(pi) + [InlineData(-2.71828183f, 0.450549534f, CrossPlatformMachineEpsilon)] // value: -(e) + [InlineData(-2.30258509f, 1.11340715f, CrossPlatformMachineEpsilon * 10)] // value: -(ln(10)) + [InlineData(-1.57079633f, 22877332.0f, 10.0f)] // value: -(pi / 2) + [InlineData(-1.44269504f, -7.76357567f, CrossPlatformMachineEpsilon * 10)] // value: -(log2(e)) + [InlineData(-1.41421356f, -6.33411917f, CrossPlatformMachineEpsilon * 10)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -2.11087684f, CrossPlatformMachineEpsilon * 10)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -1.55740772f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-0.785398163f, -1.0f, CrossPlatformMachineEpsilon * 10)] // value: -(pi / 4) + [InlineData(-0.707106781f, -0.854510432f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -0.830640878f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, -0.739302950f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, -0.463829067f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, -0.329514733f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.329514733f, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.463829067f, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.739302950f, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.830640878f, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.854510432f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (pi / 4) + [InlineData(1.0f, 1.55740772f, CrossPlatformMachineEpsilon * 10)] + [InlineData(1.12837917f, 2.11087684f, CrossPlatformMachineEpsilon * 10)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 6.33411917f, CrossPlatformMachineEpsilon * 10)] // value: (sqrt(2)) + [InlineData(1.44269504f, 7.76357567f, CrossPlatformMachineEpsilon * 10)] // value: (log2(e)) + [InlineData(1.57079633f, -22877332.0f, 10.0f)] // value: (pi / 2) + [InlineData(2.30258509f, -1.11340715f, CrossPlatformMachineEpsilon * 10)] // value: (ln(10)) + [InlineData(2.71828183f, -0.450549534f, CrossPlatformMachineEpsilon)] // value: (e) + [InlineData(3.14159265f, 0.0f, CrossPlatformMachineEpsilon)] // value: (pi) + [InlineData(float.PositiveInfinity, float.NaN, 0.0f)] + public static void Tan(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Tan(value), allowedVariance); + } + + [Theory] + [InlineData(float.NegativeInfinity, -1.0f, CrossPlatformMachineEpsilon * 10)] + [InlineData(-3.14159265f, -0.996272076f, CrossPlatformMachineEpsilon)] // value: -(pi) + [InlineData(-2.71828183f, -0.991328916f, CrossPlatformMachineEpsilon)] // value: -(e) + [InlineData(-2.30258509f, -0.980198020f, CrossPlatformMachineEpsilon)] // value: -(ln(10)) + [InlineData(-1.57079633f, -0.917152336f, CrossPlatformMachineEpsilon)] // value: -(pi / 2) + [InlineData(-1.44269504f, -0.894238946f, CrossPlatformMachineEpsilon)] // value: -(log2(e)) + [InlineData(-1.41421356f, -0.888385562f, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) + [InlineData(-1.12837917f, -0.810463806f, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) + [InlineData(-1.0f, -0.761594156f, CrossPlatformMachineEpsilon)] + [InlineData(-0.785398163f, -0.655794203f, CrossPlatformMachineEpsilon)] // value: -(pi / 4) + [InlineData(-0.707106781f, -0.608859365f, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) + [InlineData(-0.693147181f, -0.6f, CrossPlatformMachineEpsilon)] // value: -(ln(2)) + [InlineData(-0.636619772f, -0.562593600f, CrossPlatformMachineEpsilon)] // value: -(2 / pi) + [InlineData(-0.434294482f, -0.408904012f, CrossPlatformMachineEpsilon)] // value: -(log10(e)) + [InlineData(-0.318309886f, -0.307977913f, CrossPlatformMachineEpsilon)] // value: -(1 / pi) + [InlineData(-0.0f, -0.0f, 0.0f)] + [InlineData(float.NaN, float.NaN, 0.0f)] + [InlineData(0.0f, 0.0f, 0.0f)] + [InlineData(0.318309886f, 0.307977913f, CrossPlatformMachineEpsilon)] // value: (1 / pi) + [InlineData(0.434294482f, 0.408904012f, CrossPlatformMachineEpsilon)] // value: (log10(e)) + [InlineData(0.636619772f, 0.562593600f, CrossPlatformMachineEpsilon)] // value: (2 / pi) + [InlineData(0.693147181f, 0.6f, CrossPlatformMachineEpsilon)] // value: (ln(2)) + [InlineData(0.707106781f, 0.608859365f, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) + [InlineData(0.785398163f, 0.655794203f, CrossPlatformMachineEpsilon)] // value: (pi / 4) + [InlineData(1.0f, 0.761594156f, CrossPlatformMachineEpsilon)] + [InlineData(1.12837917f, 0.810463806f, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) + [InlineData(1.41421356f, 0.888385562f, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) + [InlineData(1.44269504f, 0.894238946f, CrossPlatformMachineEpsilon)] // value: (log2(e)) + [InlineData(1.57079633f, 0.917152336f, CrossPlatformMachineEpsilon)] // value: (pi / 2) + [InlineData(2.30258509f, 0.980198020f, CrossPlatformMachineEpsilon)] // value: (ln(10)) + [InlineData(2.71828183f, 0.991328916f, CrossPlatformMachineEpsilon)] // value: (e) + [InlineData(3.14159265f, 0.996272076f, CrossPlatformMachineEpsilon)] // value: (pi) + [InlineData(float.PositiveInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] + public static void Tanh(float value, float expectedResult, float allowedVariance) + { + AssertExtensions.Equal(expectedResult, MathF.Tanh(value), allowedVariance); + } + + [Fact] + public static void Truncate() + { + Assert.Equal(0.0f, MathF.Truncate(0.12345f)); + Assert.Equal(3.0f, MathF.Truncate(3.14159f)); + Assert.Equal(-3.0f, MathF.Truncate(-3.14159f)); + } + + public static IEnumerable Round_ToEven_TestData() + { + yield return new object[] { 1f, 1f }; + yield return new object[] { 0.5f, 0f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 2f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 0.49999997f, 0f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 2f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 4.5f, 4f }; + yield return new object[] { 3.1415927f, 3f }; + yield return new object[] { 2.7182817f, 3f }; + yield return new object[] { 1385.4557f, 1385f }; + yield return new object[] { 3423.4343f, 3423f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.4f, 535345f }; + yield return new object[] { 535345.6f, 535346f }; + yield return new object[] { -2.7182817f, -3f }; + yield return new object[] { 10f, 10f }; + yield return new object[] { -10f, -10f }; + yield return new object[] { -0f, -0f }; + yield return new object[] { 0f, 0f }; + yield return new object[] { float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { 3.4028235E+38f, 3.4028235E+38f }; + yield return new object[] { -3.4028235E+38f, -3.4028235E+38f }; + } + + [Theory] + [MemberData(nameof(Round_ToEven_TestData))] + public static void Round_ToEven_0(float value, float expected) + { + // Math.Round has special fast paths when MidpointRounding is a const + // Don't replace it with a variable + Assert.Equal(expected, MathF.Round(value, MidpointRounding.ToEven)); + Assert.Equal(expected, MathF.Round(value, 0, MidpointRounding.ToEven)); + } + + public static IEnumerable Round_AwayFromZero_TestData() + { + yield return new object[] { 1f, 1f }; + yield return new object[] { 0.5f, 1f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 3f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 0.49999997f, 0f }; + yield return new object[] { 1.5f, 2f }; + yield return new object[] { 2.5f, 3f }; + yield return new object[] { 3.5f, 4f }; + yield return new object[] { 4.5f, 5f }; + yield return new object[] { 3.1415927f, 3f }; + yield return new object[] { 2.7182817f, 3f }; + yield return new object[] { 1385.4557f, 1385f }; + yield return new object[] { 3423.4343f, 3423f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.5f, 535346f }; + yield return new object[] { 535345.4f, 535345f }; + yield return new object[] { 535345.6f, 535346f }; + yield return new object[] { -2.7182817f, -3f }; + yield return new object[] { 10f, 10f }; + yield return new object[] { -10f, -10f }; + yield return new object[] { -0f, -0f }; + yield return new object[] { 0f, 0f }; + yield return new object[] { float.NaN, float.NaN }; + yield return new object[] { float.PositiveInfinity, float.PositiveInfinity }; + yield return new object[] { float.NegativeInfinity, float.NegativeInfinity }; + yield return new object[] { 3.4028235E+38f, 3.4028235E+38f }; + yield return new object[] { -3.4028235E+38f, -3.4028235E+38f }; + } + + [Theory] + [MemberData(nameof(Round_AwayFromZero_TestData))] + public static void Round_AwayFromZero_0(float value, float expected) + { + // Math.Round has special fast paths when MidpointRounding is a const + // Don't replace it with a variable + Assert.Equal(expected, MathF.Round(value, MidpointRounding.AwayFromZero)); + Assert.Equal(expected, MathF.Round(value, 0, MidpointRounding.AwayFromZero)); + } + } +} diff --git a/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj b/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj new file mode 100644 index 0000000000000..ca3c94f5e5825 --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj @@ -0,0 +1,12 @@ + + + $(NetFrameworkMinimum) + + + + + + + + + From 6ec3d8d5a120be1b7a73353428cf798327dddc02 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Thu, 24 Aug 2023 11:14:15 -0600 Subject: [PATCH 02/10] bcl done --- .../src/Microsoft.Bcl.Numerics.csproj | 6 +- .../src/System/MathF.cs | 246 ++++++---- .../System/Microsoft.Bcl.Numerics.Forwards.cs | 4 + .../Microsoft.Bcl.Numerics/src/strings.resx | 72 --- .../Microsoft.Bcl.Numerics/tests/MathF.cs | 442 +----------------- 5 files changed, 178 insertions(+), 592 deletions(-) create mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/System/Microsoft.Bcl.Numerics.Forwards.cs delete mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/strings.resx diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj index a7a8603ac2e73..4fc1180f923ea 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -5,7 +5,7 @@ $(NoWarn);CS1591 - Provides MathF + Provides the System.MathF for .NET Standard 2.0 @@ -22,4 +22,8 @@ + + + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs index 6b1dec99e4d41..65ce47a097543 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs +++ b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs @@ -11,20 +11,15 @@ using System.Runtime.CompilerServices; using System.Diagnostics.Contracts; +using System.Drawing; namespace System { + /// + /// Provides constants and static methods for trigonometric, logarithmic, and other common mathematical functions. + /// public static class MathF { - private static float singleRoundLimit = 1e8f; - - private const int maxRoundingDigits = 6; - - // This table is required for the Round function which can specify the number of digits to round to - private static float[] roundPower10Single = new float[] { - 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f - }; - public const float PI = 3.14159265f; public const float E = 2.71828183f; @@ -42,26 +37,83 @@ private static unsafe bool IsNegative(float f) return (*(uint*)(&f) & 0x80000000) == 0x80000000; } + /// + /// Returns the absolute value of a single-precision floating-point number. + /// + /// The number to take the absolute value of. + /// The absolute value of public static float Abs(float x) => Math.Abs(x); + /// + /// Returns the angle whose cosine is the specified number. + /// + /// The number to take the acos of. + /// The acos of public static float Acos(float x) => (float)Math.Acos(x); + /// + /// Returns the angle whose sine is the specified number. + /// + /// The number to take the asin of. + /// The asin of public static float Asin(float x) => (float)Math.Asin(x); + /// + /// Returns the angle whose tangent is the specified number. + /// + /// The number to take the atan of. + /// The atan of public static float Atan(float x) => (float)Math.Atan(x); + /// + /// Returns the angle whose tangent is the quotient of two specified numbers. + /// + /// The first number. + /// The second number. + /// The angle whose tangent is the quotient of and public static float Atan2(float y, float x) => (float)Math.Atan2(y, x); + /// + /// Returns the smallest integral value that is greater than or equal to the specified single-precision floating-point number. + /// + /// The number to take the ceiling of. + /// The ceiling of public static float Ceiling(float x) => (float)Math.Ceiling(x); + /// + /// Returns the cosine of the specified angle. + /// + /// The angle to take the cosine of. + /// The cosine of public static float Cos(float x) => (float)Math.Cos(x); + /// + /// Returns the hyperbolic cosine of the specified angle. + /// + /// The angle to take the hyperbolic cosine of. + /// The hyperbolic cosine of public static float Cosh(float x) => (float)Math.Cosh(x); + /// + /// Returns e raised to the specified power. + /// + /// The number to raise e to. + /// e raised to the power of public static float Exp(float x) => (float)Math.Exp(x); + /// + /// Returns the largest integral value less than or equal to the specified single-precision floating-point number. + /// + /// The number to take the floor of. + /// The floor of public static float Floor(float x) => (float)Math.Floor(x); + /// + /// Returns the remainder resulting from the division of a specified number by another specified number. + /// + /// The numerator + /// The denominator + /// The result of dividing by public static float IEEERemainder(float x, float y) { if (float.IsNaN(x)) @@ -113,8 +165,19 @@ public static float IEEERemainder(float x, float y) } } + /// + /// Returns the natural (base e) logarithm of a specified number. + /// + /// The number to take the natural log of. + /// The natural log of public static float Log(float x) => (float)Math.Log(x); + /// + /// Returns the logarithm of a specified number in a specified base. + /// + /// The number to take the log of. + /// The base of the log + /// The log of with base public static float Log(float x, float y) { if (float.IsNaN(x)) @@ -140,103 +203,116 @@ public static float Log(float x, float y) return Log(x) / Log(y); } + /// + /// Returns the base 10 logarithm of a specified number. + /// + /// The number to take the base 10 log of. + /// The base 10 log of public static float Log10(float x) => (float)Math.Log10(x); + /// + /// Returns the larger of two single-precision floating-point numbers. + /// + /// The first number to compare. + /// The second number to compare. + /// The larger of and public static float Max(float x, float y) => Math.Max(x, y); + /// + /// Returns the smaller of two single-precision floating-point numbers. + /// + /// The first number to compare. + /// The second number to compare. + /// The smaller of and public static float Min(float x, float y) => Math.Min(x, y); + /// + /// Returns a specified number raised to the specified power. + /// + /// The base number. + /// The specified power. + /// raised to the power of public static float Pow(float x, float y) => (float)Math.Pow(x, y); + /// + /// Rounds a single-precision floating-point value to the nearest integral value, and rounds midpoint values to the nearest even number. + /// + /// The number to round. + /// The rounded representation of public static float Round(float x) => (float)Math.Round(x); - public static float Round(float x, int digits) - { - if ((digits < 0) || (digits > maxRoundingDigits)) - { - throw new ArgumentOutOfRangeException(nameof(digits), SR.ArgumentOutOfRange_RoundingDigits); - } - Contract.EndContractBlock(); - - return InternalRound(x, digits, MidpointRounding.ToEven); - } - - public static float Round(float x, int digits, MidpointRounding mode) - { - if ((digits < 0) || (digits > maxRoundingDigits)) - { - throw new ArgumentOutOfRangeException(nameof(digits), SR.ArgumentOutOfRange_RoundingDigits); - } - - if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidEnum, mode, nameof(MidpointRounding)), nameof(mode)); - } - Contract.EndContractBlock(); - - return InternalRound(x, digits, mode); - } - - public static float Round(float x, MidpointRounding mode) - { - if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) - { - throw new ArgumentException(SR.Format(SR.Argument_InvalidEnum, mode, nameof(MidpointRounding)), nameof(mode)); - } - Contract.EndContractBlock(); - - return InternalRound(x, 0, mode); - } - + /// + /// Rounds a single-precision floating-point value to a specified number of fractional digits, and rounds midpoint values to the nearest even number. + /// + /// The number to round. + /// How many fractional digits to keep. + /// The rounded representation of with fractional digits + public static float Round(float x, int digits) => (float)Math.Round(x, digits); + + /// + /// Rounds a single-precision floating-point value to a specified number of fractional digits using the specified rounding convention. + /// + /// The number to round. + /// How many fractional digits to keep. + /// The rounding convention to use. + /// The rounded representation of with fractional digits using rounding convention + public static float Round(float x, int digits, MidpointRounding mode) => (float)Math.Round(x, digits, mode); + + /// + /// Rounds a single-precision floating-point value to an integer using the specified rounding convention. + /// + /// The number to round. + /// The rounding convention to use. + /// The rounded representation of using rounding convention + public static float Round(float x, MidpointRounding mode) => (float)Math.Round(x, mode); + + /// + /// Returns an integer that indicates the sign of a single-precision floating-point number. + /// + /// The number check the sign of. + /// The sign of public static int Sign(float x) => Math.Sign(x); + /// + /// Returns the sine of the specified angle. + /// + /// The angle to take the sine of. + /// The sine of public static float Sin(float x) => (float)Math.Sin(x); + /// + /// Returns the hyperbolic sine of the specified angle. + /// + /// The angle to take the hyperbolic sine of. + /// The hyperbolic sine of public static float Sinh(float x) => (float)Math.Sinh(x); + /// + /// Returns the square root of a specified number. + /// + /// The number to take the square root of. + /// The square root of public static float Sqrt(float x) => (float)Math.Sqrt(x); + /// + /// Returns the tangent of the specified angle. + /// + /// The angle to take the tangent of. + /// The tangent of public static float Tan(float x) => (float)Math.Tan(x); + /// + /// Returns the hyperbolic tangent of the specified angle. + /// + /// The angle to take the hyperbolic tangent of. + /// The hyperbolic tangent of public static float Tanh(float x) => (float)Math.Tanh(x); - public static float Truncate(float x) => InternalTruncate(x); - - private static unsafe float InternalRound(float x, int digits, MidpointRounding mode) - { - if (Abs(x) < singleRoundLimit) - { - var power10 = roundPower10Single[digits]; - - x *= power10; - - if (mode == MidpointRounding.AwayFromZero) - { - var fraction = SplitFractionSingle(&x); - - if (Abs(fraction) >= 0.5f) - { - x += Sign(fraction); - } - } - else - { - x = Round(x); - } - - x /= power10; - } - - return x; - } - - private static unsafe float InternalTruncate(float x) - { - SplitFractionSingle(&x); - return x; - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern unsafe float SplitFractionSingle(float* x); + /// + /// Calculates the integral part of a specified single-precision floating-point number. + /// + /// The number to truncate. + /// The truncated representation of + public static float Truncate(float x) => (float)Math.Truncate(x); } } diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/System/Microsoft.Bcl.Numerics.Forwards.cs b/src/libraries/Microsoft.Bcl.Numerics/src/System/Microsoft.Bcl.Numerics.Forwards.cs new file mode 100644 index 0000000000000..641ce5525675f --- /dev/null +++ b/src/libraries/Microsoft.Bcl.Numerics/src/System/Microsoft.Bcl.Numerics.Forwards.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.MathF))] diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/strings.resx b/src/libraries/Microsoft.Bcl.Numerics/src/strings.resx deleted file mode 100644 index 46ed6f4ac81c3..0000000000000 --- a/src/libraries/Microsoft.Bcl.Numerics/src/strings.resx +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Non-negative number required. - - - The number of bytes requested is too large. The number of bytes produced by SP800108HmacCounterKdf cannot exceed 536,870,911 bytes. - - - The value cannot be an empty string. - - - '{0}' is not a known hash algorithm. - - diff --git a/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs index 3712ac992abbe..cc615e59d433a 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs +++ b/src/libraries/Microsoft.Bcl.Numerics/tests/MathF.cs @@ -287,16 +287,6 @@ public static void Atan2(float y, float x, float expectedResult, float allowedVa AssertExtensions.Equal(expectedResult, MathF.Atan2(y, x), allowedVariance); } - [Theory] - [InlineData(float.NegativeInfinity, float.NegativeInfinity, -2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: -(3 * pi / 4) - [InlineData(float.NegativeInfinity, float.PositiveInfinity, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) - [InlineData(float.PositiveInfinity, float.NegativeInfinity, 2.35619449f, CrossPlatformMachineEpsilon * 10)] // expected: (3 * pi / 4 - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - public static void Atan2_IEEE(float y, float x, float expectedResult, float allowedVariance) - { - AssertExtensions.Equal(expectedResult, MathF.Atan2(y, x), allowedVariance); - } - [Theory] [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f)] [InlineData(-3.14159265f, -3.0f, 0.0f)] // value: -(pi) @@ -307,12 +297,12 @@ public static void Atan2_IEEE(float y, float x, float expectedResult, float allo [InlineData(-1.41421356f, -1.0f, 0.0f)] // value: -(sqrt(2)) [InlineData(-1.12837917f, -1.0f, 0.0f)] // value: -(2 / sqrt(pi)) [InlineData(-1.0f, -1.0f, 0.0f)] - [InlineData(-0.785398163f, -0.0f, 0.0f)] // value: -(pi / 4) - [InlineData(-0.707106781f, -0.0f, 0.0f)] // value: -(1 / sqrt(2)) - [InlineData(-0.693147181f, -0.0f, 0.0f)] // value: -(ln(2)) - [InlineData(-0.636619772f, -0.0f, 0.0f)] // value: -(2 / pi) - [InlineData(-0.434294482f, -0.0f, 0.0f)] // value: -(log10(e)) - [InlineData(-0.318309886f, -0.0f, 0.0f)] // value: -(1 / pi) + [InlineData(-0.785398163f, 0.0f, 0.0f)] // value: (pi / 4) + [InlineData(-0.707106781f, 0.0f, 0.0f)] // value: (1 / sqrt(2)) + [InlineData(-0.693147181f, 0.0f, 0.0f)] // value: (ln(2)) + [InlineData(-0.636619772f, 0.0f, 0.0f)] // value: (2 / pi) + [InlineData(-0.434294482f, 0.0f, 0.0f)] // value: (log10(e)) + [InlineData(-0.318309886f, 0.0f, 0.0f)] // value: (1 / pi) [InlineData(-0.0f, -0.0f, 0.0f)] [InlineData(float.NaN, float.NaN, 0.0f)] [InlineData(0.0f, 0.0f, 0.0f)] @@ -565,50 +555,6 @@ public static void LogWithBase() Assert.Equal(float.NaN, MathF.Log(float.NegativeInfinity, 3.0f)); } -#if NETCOREAPP2_0_OR_GREATER - [Theory] - [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] - [InlineData(-0.113314732f, float.NaN, 0.0f)] - [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(0.113314732f, -3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi) - [InlineData(0.151955223f, -2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: -(e) - [InlineData(0.202699566f, -2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: -(ln(10)) - [InlineData(0.336622537f, -1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: -(pi / 2) - [InlineData(0.367879441f, -1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: -(log2(e)) - [InlineData(0.375214227f, -1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: -(sqrt(2)) - [InlineData(0.457429347f, -1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: -(2 / sqrt(pi)) - [InlineData(0.5f, -1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.580191810f, -0.785398163f, CrossPlatformMachineEpsilon)] // expected: -(pi / 4) - [InlineData(0.612547327f, -0.707106781f, CrossPlatformMachineEpsilon)] // expected: -(1 / sqrt(2)) - [InlineData(0.618503138f, -0.693147181f, CrossPlatformMachineEpsilon)] // expected: -(ln(2)) - [InlineData(0.643218242f, -0.636619772f, CrossPlatformMachineEpsilon)] // expected: -(2 / pi) - [InlineData(0.740055574f, -0.434294482f, CrossPlatformMachineEpsilon)] // expected: -(log10(e)) - [InlineData(0.802008879f, -0.318309886f, CrossPlatformMachineEpsilon)] // expected: -(1 / pi) - [InlineData(1, 0.0f, 0.0f)] - [InlineData(1.24686899f, 0.318309886f, CrossPlatformMachineEpsilon)] // expected: (1 / pi) - [InlineData(1.35124987f, 0.434294482f, CrossPlatformMachineEpsilon)] // expected: (log10(e)) - [InlineData(1.55468228f, 0.636619772f, CrossPlatformMachineEpsilon)] // expected: (2 / pi) - [InlineData(1.61680667f, 0.693147181f, CrossPlatformMachineEpsilon)] // expected: (ln(2)) - [InlineData(1.63252692f, 0.707106781f, CrossPlatformMachineEpsilon)] // expected: (1 / sqrt(2)) - [InlineData(1.72356793f, 0.785398163f, CrossPlatformMachineEpsilon)] // expected: (pi / 4) - [InlineData(2, 1.0f, CrossPlatformMachineEpsilon * 10)] // value: (e) - [InlineData(2.18612996f, 1.12837917f, CrossPlatformMachineEpsilon * 10)] // expected: (2 / sqrt(pi)) - [InlineData(2.66514414f, 1.41421356f, CrossPlatformMachineEpsilon * 10)] // expected: (sqrt(2)) - [InlineData(2.71828183f, 1.44269504f, CrossPlatformMachineEpsilon * 10)] // expected: (log2(e)) - [InlineData(2.97068642f, 1.57079633f, CrossPlatformMachineEpsilon * 10)] // expected: (pi / 2) - [InlineData(4.93340967f, 2.30258509f, CrossPlatformMachineEpsilon * 10)] // expected: (ln(10)) - [InlineData(6.58088599f, 2.71828183f, CrossPlatformMachineEpsilon * 10)] // expected: (e) - [InlineData(8.82497783f, 3.14159265f, CrossPlatformMachineEpsilon * 10)] // expected: (pi) - [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.0f)] - public static void Log2(float value, float expectedResult, float allowedVariance) - { - AssertExtensions.Equal(expectedResult, MathF.Log2(value), allowedVariance); - } - -#endif - [Theory] [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: -(pi) @@ -668,7 +614,7 @@ public static void Log10(float value, float expectedResult, float allowedVarianc [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, -0.0f, 0.0f)] + [InlineData(0.0f, -0.0f, -0.0f)] [InlineData(2.0f, -3.0f, 2.0f)] [InlineData(-3.0f, 2.0f, 2.0f)] [InlineData(3.0f, -2.0f, 3.0f)] @@ -676,80 +622,8 @@ public static void Log10(float value, float expectedResult, float allowedVarianc public static void Max(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.Max(x, y), 0.0f); - - //if (float.IsNaN(x)) - //{ - // // Toggle the sign of the NaN to validate both +NaN and -NaN behave the same. - // // Negate should work as well but the JIT may constant fold or do other tricks - // // and normalize to a single NaN form so we do bitwise tricks to ensure we test - // // the right thing. - - // uint bits = BitConverter.SingleToUInt32Bits(x); - // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - // x = BitConverter.UInt32BitsToSingle(bits); - - // AssertExtensions.Equal(expectedResult, Math.Max(x, y), 0.0f); - //} - - //if (float.IsNaN(y)) - //{ - // uint bits = BitConverter.SingleToUInt32Bits(y); - // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - // y = BitConverter.UInt32BitsToSingle(bits); - - // AssertExtensions.Equal(expectedResult, Math.Max(x, y), 0.0f); - //} - } - -#if NETCOREAPP2_0_OR_GREATER - [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.PositiveInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.PositiveInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MaxValue)] - [InlineData(float.MaxValue, float.MinValue, float.MaxValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, float.NaN)] - [InlineData(1.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, 0.0f)] - [InlineData(0.0f, -0.0f, 0.0f)] - [InlineData(2.0f, -3.0f, -3.0f)] - [InlineData(-3.0f, 2.0f, -3.0f)] - [InlineData(3.0f, -2.0f, 3.0f)] - [InlineData(-2.0f, 3.0f, 3.0f)] - public static void MaxMagnitude(float x, float y, float expectedResult) - { - AssertExtensions.Equal(expectedResult, MathF.MaxMagnitude(x, y), 0.0f); - - if (float.IsNaN(x)) - { - // Toggle the sign of the NaN to validate both +NaN and -NaN behave the same. - // Negate should work as well but the JIT may constant fold or do other tricks - // and normalize to a single NaN form so we do bitwise tricks to ensure we test - // the right thing. - - uint bits = BitConverter.SingleToUInt32Bits(x); - bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - x = BitConverter.UInt32BitsToSingle(bits); - - AssertExtensions.Equal(expectedResult, Math.MaxMagnitude(x, y), 0.0f); - } - - if (float.IsNaN(y)) - { - uint bits = BitConverter.SingleToUInt32Bits(y); - bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - y = BitConverter.UInt32BitsToSingle(bits); - - AssertExtensions.Equal(expectedResult, Math.MaxMagnitude(x, y), 0.0f); - } } -#endif - [Theory] [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] @@ -762,7 +636,7 @@ public static void MaxMagnitude(float x, float y, float expectedResult) [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, -0.0f)] + [InlineData(-0.0f, 0.0f, 0.0f)] [InlineData(0.0f, -0.0f, -0.0f)] [InlineData(2.0f, -3.0f, -3.0f)] [InlineData(-3.0f, 2.0f, -3.0f)] @@ -771,69 +645,8 @@ public static void MaxMagnitude(float x, float y, float expectedResult) public static void Min(float x, float y, float expectedResult) { AssertExtensions.Equal(expectedResult, MathF.Min(x, y), 0.0f); - - //if (float.IsNaN(x)) - //{ - // uint bits = BitConverter.SingleToUInt32Bits(x); - // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - // x = BitConverter.UInt32BitsToSingle(bits); - - // AssertExtensions.Equal(expectedResult, Math.Min(x, y), 0.0f); - //} - - //if (float.IsNaN(y)) - //{ - // uint bits = BitConverter.SingleToUInt32Bits(y); - // bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - // y = BitConverter.UInt32BitsToSingle(bits); - - // AssertExtensions.Equal(expectedResult, Math.Min(x, y), 0.0f); - //} } -#if NETCOREAPP2_0_OR_GREATER - - [Theory] - [InlineData(float.NegativeInfinity, float.PositiveInfinity, float.NegativeInfinity)] - [InlineData(float.PositiveInfinity, float.NegativeInfinity, float.NegativeInfinity)] - [InlineData(float.MinValue, float.MaxValue, float.MinValue)] - [InlineData(float.MaxValue, float.MinValue, float.MinValue)] - [InlineData(float.NaN, float.NaN, float.NaN)] - [InlineData(float.NaN, 1.0f, float.NaN)] - [InlineData(1.0f, float.NaN, float.NaN)] - [InlineData(float.PositiveInfinity, float.NaN, float.NaN)] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN)] - [InlineData(float.NaN, float.PositiveInfinity, float.NaN)] - [InlineData(float.NaN, float.NegativeInfinity, float.NaN)] - [InlineData(-0.0f, 0.0f, -0.0f)] - [InlineData(0.0f, -0.0f, -0.0f)] - [InlineData(2.0f, -3.0f, 2.0f)] - [InlineData(-3.0f, 2.0f, 2.0f)] - [InlineData(3.0f, -2.0f, -2.0f)] - [InlineData(-2.0f, 3.0f, -2.0f)] - public static void MinMagnitude(float x, float y, float expectedResult) - { - AssertExtensions.Equal(expectedResult, MathF.MinMagnitude(x, y), 0.0f); - - if (float.IsNaN(x)) - { - uint bits = BitConverter.SingleToUInt32Bits(x); - bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - x = BitConverter.UInt32BitsToSingle(bits); - - AssertExtensions.Equal(expectedResult, Math.MinMagnitude(x, y), 0.0f); - } - - if (float.IsNaN(y)) - { - uint bits = BitConverter.SingleToUInt32Bits(y); - bits ^= BitConverter.SingleToUInt32Bits(-0.0f); - y = BitConverter.UInt32BitsToSingle(bits); - - AssertExtensions.Equal(expectedResult, Math.MinMagnitude(x, y), 0.0f); - } - } -#endif [Theory] [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f, 0.0f)] @@ -985,99 +798,6 @@ public static void Pow(float x, float y, float expectedResult, float allowedVari AssertExtensions.Equal(expectedResult, MathF.Pow(x, y), allowedVariance); } - [Theory] - [InlineData(-1.0f, float.NegativeInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(-1.0f, float.PositiveInfinity, 1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(float.NaN, -0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(float.NaN, 0.0f, 1.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.0f, float.NaN, 1.0f, CrossPlatformMachineEpsilon * 10)] - public static void Pow_IEEE(float x, float y, float expectedResult, float allowedVariance) - { - AssertExtensions.Equal(expectedResult, MathF.Pow(x, y), allowedVariance); - } - -#if NETCOREAPP2_0_OR_GREATER - - [Theory] - [InlineData(float.NegativeInfinity, -0.0f, 0.0f)] - [InlineData(-3.14159265f, -0.318309873f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi) - [InlineData(-2.71828183f, -0.36787945f, CrossPlatformMachineEpsilonForEstimates)] // value: (e) - [InlineData(-2.30258509f, -0.434294462f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(10)) - [InlineData(-1.57079633f, -0.636619747f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 2) - [InlineData(-1.44269504f, -0.693147182f, CrossPlatformMachineEpsilonForEstimates)] // value: (log2(e)) - [InlineData(-1.41421356f, -0.707106769f, CrossPlatformMachineEpsilonForEstimates)] // value: (sqrt(2)) - [InlineData(-1.12837917f, -0.886226892f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / sqrt(pi)) - [InlineData(-1.0f, -1.0f, CrossPlatformMachineEpsilonForEstimates)] - [InlineData(-0.785398163f, -1.27323949f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 4) - [InlineData(-0.707106781f, -1.41421354f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / sqrt(2)) - [InlineData(-0.693147181f, -1.44269502f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(2)) - [InlineData(-0.636619772f, -1.57079637f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / pi) - [InlineData(-0.434294482f, -2.30258512f, CrossPlatformMachineEpsilonForEstimates)] // value: (log10(e)) - [InlineData(-0.318309886f, -3.14159274f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / pi) - [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, float.PositiveInfinity, 0.0f)] - [InlineData(0.318309886f, 3.14159274f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / pi) - [InlineData(0.434294482f, 2.30258512f, CrossPlatformMachineEpsilonForEstimates)] // value: (log10(e)) - [InlineData(0.636619772f, 1.57079637f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / pi) - [InlineData(0.693147181f, 1.44269502f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(2)) - [InlineData(0.707106781f, 1.41421354f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / sqrt(2)) - [InlineData(0.785398163f, 1.27323949f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 4) - [InlineData(1.0f, 1.0f, CrossPlatformMachineEpsilonForEstimates)] - [InlineData(1.12837917f, 0.886226892f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / sqrt(pi)) - [InlineData(1.41421356f, 0.707106769f, CrossPlatformMachineEpsilonForEstimates)] // value: (sqrt(2)) - [InlineData(1.44269504f, 0.693147182f, CrossPlatformMachineEpsilonForEstimates)] // value: (log2(e)) - [InlineData(1.57079633f, 0.636619747f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 2) - [InlineData(2.30258509f, 0.434294462f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(10)) - [InlineData(2.71828183f, 0.36787945f, CrossPlatformMachineEpsilonForEstimates)] // value: (e) - [InlineData(3.14159265f, 0.318309873f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi) - [InlineData(float.PositiveInfinity, 0.0f, 0.0f)] - public static void ReciprocalEstimate(float value, float expectedResult, float allowedVariance) - { - AssertExtensions.Equal(expectedResult, MathF.ReciprocalEstimate(value), allowedVariance); - } - - [Theory] - [InlineData(float.NegativeInfinity, float.NaN, 0.0f)] - [InlineData(-3.14159265f, float.NaN, 0.0f)] // value: (pi) - [InlineData(-2.71828183f, float.NaN, 0.0f)] // value: (e) - [InlineData(-2.30258509f, float.NaN, 0.0f)] // value: (ln(10)) - [InlineData(-1.57079633f, float.NaN, 0.0f)] // value: (pi / 2) - [InlineData(-1.44269504f, float.NaN, 0.0f)] // value: (log2(e)) - [InlineData(-1.41421356f, float.NaN, 0.0f)] // value: (sqrt(2)) - [InlineData(-1.12837917f, float.NaN, 0.0f)] // value: (2 / sqrt(pi)) - [InlineData(-1.0f, float.NaN, 0.0f)] - [InlineData(-0.785398163f, float.NaN, 0.0f)] // value: (pi / 4) - [InlineData(-0.707106781f, float.NaN, 0.0f)] // value: (1 / sqrt(2)) - [InlineData(-0.693147181f, float.NaN, 0.0f)] // value: (ln(2)) - [InlineData(-0.636619772f, float.NaN, 0.0f)] // value: (2 / pi) - [InlineData(-0.434294482f, float.NaN, 0.0f)] // value: (log10(e)) - [InlineData(-0.318309886f, float.NaN, 0.0f)] // value: (1 / pi) - [InlineData(-0.0f, float.NegativeInfinity, 0.0f)] - [InlineData(float.NaN, float.NaN, 0.0f)] - [InlineData(0.0f, float.PositiveInfinity, 0.0f)] - [InlineData(0.318309886f, 1.7724539f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / pi) - [InlineData(0.434294482f, 1.51742709f, CrossPlatformMachineEpsilonForEstimates)] // value: (log10(e)) - [InlineData(0.636619772f, 1.25331414f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / pi) - [InlineData(0.693147181f, 1.2011224f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(2)) - [InlineData(0.707106781f, 1.18920708f, CrossPlatformMachineEpsilonForEstimates)] // value: (1 / sqrt(2)) - [InlineData(0.785398163f, 1.12837911f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 4) - [InlineData(1.0f, 1.0f, CrossPlatformMachineEpsilonForEstimates)] - [InlineData(1.12837917f, 0.941396296f, CrossPlatformMachineEpsilonForEstimates)] // value: (2 / sqrt(pi)) - [InlineData(1.41421356f, 0.840896428f, CrossPlatformMachineEpsilonForEstimates)] // value: (sqrt(2)) - [InlineData(1.44269504f, 0.832554638f, CrossPlatformMachineEpsilonForEstimates)] // value: (log2(e)) - [InlineData(1.57079633f, 0.797884583f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi / 2) - [InlineData(2.30258509f, 0.659010231f, CrossPlatformMachineEpsilonForEstimates)] // value: (ln(10)) - [InlineData(2.71828183f, 0.606530666f, CrossPlatformMachineEpsilonForEstimates)] // value: (e) - [InlineData(3.14159265f, 0.564189553f, CrossPlatformMachineEpsilonForEstimates)] // value: (pi) - [InlineData(float.PositiveInfinity, 0.0f, 0.0f)] - public static void ReciprocalSqrtEstimate(float value, float expectedResult, float allowedVariance) - { - AssertExtensions.Equal(expectedResult, MathF.ReciprocalSqrtEstimate(value), allowedVariance); - } - -#endif - public static IEnumerable Round_Digits_TestData { get @@ -1095,29 +815,6 @@ public static IEnumerable Round_Digits_TestData yield return new object[] { 0, 0, 3, MidpointRounding.AwayFromZero }; yield return new object[] { 3.42156f, 3.422f, 3, MidpointRounding.AwayFromZero }; yield return new object[] { -3.42156f, -3.422f, 3, MidpointRounding.AwayFromZero }; -#if NETCOREAPP2_0_OR_GREATER - - yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToZero }; - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToZero }; - yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToZero }; - yield return new object[] { 0, 0, 3, MidpointRounding.ToZero }; - yield return new object[] { 3.42156f, 3.421f, 3, MidpointRounding.ToZero }; - yield return new object[] { -3.42156f, -3.421f, 3, MidpointRounding.ToZero }; - - yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToNegativeInfinity }; - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToNegativeInfinity }; - yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToNegativeInfinity }; - yield return new object[] { 0, 0, 3, MidpointRounding.ToNegativeInfinity }; - yield return new object[] { 3.42156f, 3.421f, 3, MidpointRounding.ToNegativeInfinity }; - yield return new object[] { -3.42156f, -3.422f, 3, MidpointRounding.ToNegativeInfinity }; - - yield return new object[] { float.NaN, float.NaN, 3, MidpointRounding.ToPositiveInfinity }; - yield return new object[] { float.PositiveInfinity, float.PositiveInfinity, 3, MidpointRounding.ToPositiveInfinity }; - yield return new object[] { float.NegativeInfinity, float.NegativeInfinity, 3, MidpointRounding.ToPositiveInfinity }; - yield return new object[] { 0, 0, 3, MidpointRounding.ToPositiveInfinity }; - yield return new object[] { 3.42156f, 3.422f, 3, MidpointRounding.ToPositiveInfinity }; - yield return new object[] { -3.42156f, -3.421f, 3, MidpointRounding.ToPositiveInfinity }; -#endif } } @@ -1137,10 +834,6 @@ public static void Round() [Theory] [InlineData(MidpointRounding.ToEven)] [InlineData(MidpointRounding.AwayFromZero)] -#if NETCOREAPP2_0_OR_GREATER - [InlineData(MidpointRounding.ToNegativeInfinity)] - [InlineData(MidpointRounding.ToPositiveInfinity)] -#endif public static void Round_Digits_ByMidpointRounding(MidpointRounding mode) { Assert.Equal(float.PositiveInfinity, MathF.Round(float.PositiveInfinity, 3, mode)); @@ -1154,80 +847,6 @@ public static void Round_Digits(float x, float expected, int digits, MidpointRou AssertExtensions.Equal(expected, MathF.Round(x, digits, mode), CrossPlatformMachineEpsilon * 10); } -#if NETCOREAPP2_0_OR_GREATER - - [Theory] - [InlineData(float.NegativeInfinity, unchecked((int)(0x7FFFFFFF)), float.NegativeInfinity, 0)] - [InlineData(float.PositiveInfinity, unchecked((int)(0x7FFFFFFF)), float.PositiveInfinity, 0)] - [InlineData(float.NaN, 0, float.NaN, 0)] - [InlineData(float.NaN, 0, float.NaN, 0)] - [InlineData(float.PositiveInfinity, 0, float.PositiveInfinity, 0)] - [InlineData(float.NaN, 0, float.NaN, 0)] - [InlineData(float.NaN, 1, float.NaN, 0)] - [InlineData(float.PositiveInfinity, 2147483647, float.PositiveInfinity, 0)] - [InlineData(float.PositiveInfinity, -2147483647, float.PositiveInfinity, 0)] - [InlineData(float.NaN, 2147483647, float.NaN, 0)] - [InlineData(-0.0f, unchecked((int)(0x80000000)), -0.0f, 0)] - [InlineData(float.NaN, unchecked((int)(0x7FFFFFFF)), float.NaN, 0)] - [InlineData(0, unchecked((int)(0x80000000)), 0, 0)] - [InlineData(0.113314732f, -4, 0.00708217081f, CrossPlatformMachineEpsilon / 100)] - [InlineData(-0.113314732f, -3, -0.0141643415f, CrossPlatformMachineEpsilon / 10)] - [InlineData(0.151955223f, -3, 0.0189944021f, CrossPlatformMachineEpsilon / 10)] - [InlineData(0.202699566f, -3, 0.0253374465f, CrossPlatformMachineEpsilon / 10)] - [InlineData(0.336622537f, -2, 0.084155634f, CrossPlatformMachineEpsilon / 10)] - [InlineData(0.367879441f, -2, 0.0919698626f, CrossPlatformMachineEpsilon / 10)] - [InlineData(0.375214227f, -2, 0.0938035548f, CrossPlatformMachineEpsilon / 10)] - [InlineData(0.457429347f, -2, 0.114357337f, CrossPlatformMachineEpsilon)] - [InlineData(0.5f, -1, 0.25f, CrossPlatformMachineEpsilon)] - [InlineData(0.580191810f, -1, 0.290095896f, CrossPlatformMachineEpsilon)] - [InlineData(0.612547327f, -1, 0.306273669f, CrossPlatformMachineEpsilon)] - [InlineData(0.618503138f, -1, 0.309251577f, CrossPlatformMachineEpsilon)] - [InlineData(0.643218242f, -1, 0.321609110f, CrossPlatformMachineEpsilon)] - [InlineData(0.740055574f, -1, 0.370027781f, CrossPlatformMachineEpsilon)] - [InlineData(0.802008879f, -1, 0.401004434f, CrossPlatformMachineEpsilon)] - [InlineData(0, 2147483647, 0, CrossPlatformMachineEpsilon)] - [InlineData(0, -2147483647, 0, CrossPlatformMachineEpsilon)] - [InlineData(0, 2147483647, 0, CrossPlatformMachineEpsilon)] - [InlineData(1, -1, 0.5, CrossPlatformMachineEpsilon)] - [InlineData(1, 0, 1, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.24686899f, 0, 1.24686899f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.35124987f, 0, 1.35124987f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.55468228f, 0, 1.55468228f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.61680667f, 0, 1.61680667f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.63252692f, 0, 1.63252692f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.72356793f, 0, 1.72356793f, CrossPlatformMachineEpsilon * 10)] - [InlineData(2, 1, 4, CrossPlatformMachineEpsilon * 10)] - [InlineData(2.18612996f, 1, 4.37225992f, CrossPlatformMachineEpsilon * 10)] - [InlineData(2.66514414f, 1, 5.33028829f, CrossPlatformMachineEpsilon * 10)] - [InlineData(2.71828183f, 1, 5.43656366f, CrossPlatformMachineEpsilon * 10)] - [InlineData(2.97068642f, 1, 5.94137285f, CrossPlatformMachineEpsilon * 10)] - [InlineData(1, 0, 1, CrossPlatformMachineEpsilon * 10)] - [InlineData(1, 1, 2, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.7014118E+38, -276, 1E-45, CrossPlatformMachineEpsilon * 10)] - [InlineData(1E-45, 276, 1.7014118E+38, CrossPlatformMachineEpsilon * 10)] - [InlineData(1.0002441, -149, 1E-45, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.74999994, -148, 1E-45, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.50000066, -128, 1.46937E-39, CrossPlatformMachineEpsilon * 10)] - [InlineData(-8.066849, -2, -2.0167122, CrossPlatformMachineEpsilon * 10)] - [InlineData(4.3452396, -1, 2.1726198, CrossPlatformMachineEpsilon * 10)] - [InlineData(-8.3814335, 0, -8.3814335, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.6619859, 3, 5.295887, CrossPlatformMachineEpsilon * 10)] - [InlineData(-0.40660393, 4, -6.505663, CrossPlatformMachineEpsilon * 10)] - [InlineData(-6.5316734, 1, -13.063347, CrossPlatformMachineEpsilon * 100)] - [InlineData(9.267057, 2, 37.06823, CrossPlatformMachineEpsilon * 100)] - [InlineData(0.56175977, 5, 17.976313, CrossPlatformMachineEpsilon * 100)] - [InlineData(0.7741523, 6, 49.545746, CrossPlatformMachineEpsilon * 100)] - [InlineData(-0.6787637, 7, -86.88175, CrossPlatformMachineEpsilon * 100)] - [InlineData(4.93340967f, 2, 19.7336387f, CrossPlatformMachineEpsilon * 100)] - [InlineData(6.58088599f, 2, 26.3235440f, CrossPlatformMachineEpsilon * 100)] - [InlineData(8.82497783f, 3, 70.5998226f, CrossPlatformMachineEpsilon * 100)] - public static void ScaleB(float x, int n, float expectedResult, float allowedVariance) - { - AssertExtensions.Equal(expectedResult, MathF.ScaleB(x, n), allowedVariance); - } - -#endif - [Fact] public static void Sign() { @@ -1279,51 +898,6 @@ public static void Sin(float value, float expectedResult, float allowedVariance) AssertExtensions.Equal(expectedResult, MathF.Sin(value), allowedVariance); } -#if NETCOREAPP2_0_OR_GREATER - - [Theory] - [InlineData(float.NegativeInfinity, float.NaN, float.NaN, 0.0f, 0.0f)] - [InlineData(-3.14159265f, -0.0f, -1.0f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon * 10)] // value: -(pi) - [InlineData(-2.71828183f, -0.410781291f, -0.911733918f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(e) - [InlineData(-2.30258509f, -0.743980337f, -0.668201510f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(ln(10)) - [InlineData(-1.57079633f, -1.0f, 0.0f, CrossPlatformMachineEpsilon * 10, CrossPlatformMachineEpsilon)] // value: -(pi / 2) - [InlineData(-1.44269504f, -0.991806244f, 0.127751218f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(log2(e)) - [InlineData(-1.41421356f, -0.987765946f, 0.155943695f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(sqrt(2)) - [InlineData(-1.12837917f, -0.903719457f, 0.428125148f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(2 / sqrt(pi)) - [InlineData(-1.0f, -0.841470985f, 0.540302306f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] - [InlineData(-0.785398163f, -0.707106781f, 0.707106781f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(pi / 4), expected_sin: -(1 / sqrt(2)), expected_cos: 1 - [InlineData(-0.707106781f, -0.649636939f, 0.760244597f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(1 / sqrt(2)) - [InlineData(-0.693147181f, -0.638961276f, 0.769238901f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(ln(2)) - [InlineData(-0.636619772f, -0.594480769f, 0.804109828f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(2 / pi) - [InlineData(-0.434294482f, -0.420770483f, 0.907167129f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(log10(e)) - [InlineData(-0.318309886f, -0.312961796f, 0.949765715f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: -(1 / pi) - [InlineData(-0.0f, -0.0f, 1.0f, 0.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(float.NaN, float.NaN, float.NaN, 0.0f, 0.0f)] - [InlineData(0.0f, 0.0f, 1.0f, 0.0f, CrossPlatformMachineEpsilon * 10)] - [InlineData(0.318309886f, 0.312961796f, 0.949765715f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (1 / pi) - [InlineData(0.434294482f, 0.420770483f, 0.907167129f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (log10(e)) - [InlineData(0.636619772f, 0.594480769f, 0.804109828f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (2 / pi) - [InlineData(0.693147181f, 0.638961276f, 0.769238901f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (ln(2)) - [InlineData(0.707106781f, 0.649636939f, 0.760244597f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (1 / sqrt(2)) - [InlineData(0.785398163f, 0.707106781f, 0.707106781f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (pi / 4), expected_sin: (1 / sqrt(2)), expected_cos: 1 - [InlineData(1.0f, 0.841470985f, 0.540302306f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] - [InlineData(1.12837917f, 0.903719457f, 0.428125148f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (2 / sqrt(pi)) - [InlineData(1.41421356f, 0.987765946f, 0.155943695f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (sqrt(2)) - [InlineData(1.44269504f, 0.991806244f, 0.127751218f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (log2(e)) - [InlineData(1.57079633f, 1.0f, 0.0f, CrossPlatformMachineEpsilon * 10, CrossPlatformMachineEpsilon)] // value: (pi / 2) - [InlineData(2.30258509f, 0.743980337f, -0.668201510f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (ln(10)) - [InlineData(2.71828183f, 0.410781291f, -0.911733918f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon)] // value: (e) - [InlineData(3.14159265f, 0.0f, -1.0f, CrossPlatformMachineEpsilon, CrossPlatformMachineEpsilon * 10)] // value: (pi) - [InlineData(float.PositiveInfinity, float.NaN, float.NaN, 0.0f, 0.0f)] - public static void SinCos(float value, float expectedResultSin, float expectedResultCos, float allowedVarianceSin, float allowedVarianceCos) - { - (float resultSin, float resultCos) = MathF.SinCos(value); - AssertExtensions.Equal(expectedResultSin, resultSin, allowedVarianceSin); - AssertExtensions.Equal(expectedResultCos, resultCos, allowedVarianceCos); - } - -#endif - [Theory] [InlineData(float.NegativeInfinity, float.NegativeInfinity, 0.0f)] [InlineData(-3.14159265f, -11.5487394f, CrossPlatformMachineEpsilon * 100)] // value: -(pi) From dd00b6bda4f1e4905613e71594436f56f65b0bc8 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Thu, 24 Aug 2023 14:32:36 -0600 Subject: [PATCH 03/10] added explicit 2.1 target --- .../ref/Microsoft.Bcl.Numerics.csproj | 6 +++--- .../src/Microsoft.Bcl.Numerics.csproj | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj index f6a861851a34d..a7e06b6c6b49e 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj @@ -1,11 +1,11 @@ - $(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum) + $(NetCoreAppCurrent);netstandard2.0;netstandard2.1;$(NetFrameworkMinimum) - + - + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj index 4fc1180f923ea..e371ae173be69 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -1,6 +1,6 @@ - $(NetCoreAppCurrent);netstandard2.0;$(NetFrameworkMinimum) + $(NetCoreAppCurrent);netstandard2.0;netstandard2.1;$(NetFrameworkMinimum) true $(NoWarn);CS1591 @@ -17,12 +17,12 @@ true - + - + From 92693eb72416d29d4492aa9189cf063de5987ca4 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Thu, 24 Aug 2023 15:10:19 -0600 Subject: [PATCH 04/10] Minor doc updates --- .../Microsoft.Bcl.Numerics/src/System/MathF.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs index 65ce47a097543..04efd89e968c5 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs +++ b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs @@ -9,6 +9,16 @@ //This class contains only static members and doesn't require serialization. +//For most of this implementation for .NET Framework we just defer to System.Math and do a cast internally from single to double. +//We do this because it safer and less likely to break people since that is what they are alrady doing. Also, adding in the +//extra pinvokes needed to not do this route would probably incur an extra overhead that would be undersired. + +//For any version of .NET Core this just forwards directly to the MathF implementation inside the runtime. + +//There are a few cases where .NET Framework handles things differently than .NET Core does. For example, it returns -0 and +0 +//when using things like Min/Max, and they count as different values from each other. This is fixed in .NET Core, but since its +//inherent in .NET Framework we decided to leave that behavior as is for this BCL. + using System.Runtime.CompilerServices; using System.Diagnostics.Contracts; using System.Drawing; From 78bc22e80ded9c8882c26f2dea2dd02bef76f929 Mon Sep 17 00:00:00 2001 From: Michael Sharp <51342856+michaelgsharp@users.noreply.github.com> Date: Fri, 25 Aug 2023 10:45:54 -0600 Subject: [PATCH 05/10] Apply suggestions from code review Co-authored-by: Viktor Hofer --- .../ref/Microsoft.Bcl.Numerics.csproj | 11 ++++++----- .../src/Microsoft.Bcl.Numerics.csproj | 11 ++++++----- .../tests/Microsoft.Bcl.Numerics.Tests.csproj | 5 ++++- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj index a7e06b6c6b49e..1bf08ede702ff 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj @@ -1,11 +1,12 @@ + $(NetCoreAppCurrent);netstandard2.0;netstandard2.1;$(NetFrameworkMinimum) - - - - - + + + + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj index e371ae173be69..bfea1ebf2c0d3 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -1,19 +1,20 @@ + - $(NetCoreAppCurrent);netstandard2.0;netstandard2.1;$(NetFrameworkMinimum) + netstandard2.0;$(NetFrameworkMinimum);netstandard2.1 true $(NoWarn);CS1591 Provides the System.MathF for .NET Standard 2.0 - + true - true + true true diff --git a/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj b/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj index ca3c94f5e5825..24bf98fa16671 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/tests/Microsoft.Bcl.Numerics.Tests.csproj @@ -1,7 +1,9 @@ + - $(NetFrameworkMinimum) + $(NetFrameworkMinimum) + @@ -9,4 +11,5 @@ + From 6a7b03618d08ee9045846756248fe86ddf0c985c Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Fri, 25 Aug 2023 10:53:27 -0600 Subject: [PATCH 06/10] fixes from PR comments --- .../src/Microsoft.Bcl.Numerics.csproj | 15 ++- .../src/Resources/strings.resx | 126 ------------------ .../src/System/MathF.cs | 8 +- 3 files changed, 17 insertions(+), 132 deletions(-) delete mode 100644 src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj index bfea1ebf2c0d3..8a44f05557c49 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -3,7 +3,7 @@ netstandard2.0;$(NetFrameworkMinimum);netstandard2.1 true - $(NoWarn);CS1591 + $(NoWarn) Provides the System.MathF for .NET Standard 2.0 @@ -18,13 +18,20 @@ true - + - - + + + + + + + + + diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx b/src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx deleted file mode 100644 index 4f074235ffe0f..0000000000000 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Resources/strings.resx +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Rounding digits must be between 0 and 15, inclusive. - - - The Enum type should contain one and only one instance field. - - \ No newline at end of file diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs index 04efd89e968c5..128a3174ad0c4 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs +++ b/src/libraries/Microsoft.Bcl.Numerics/src/System/MathF.cs @@ -19,9 +19,7 @@ //when using things like Min/Max, and they count as different values from each other. This is fixed in .NET Core, but since its //inherent in .NET Framework we decided to leave that behavior as is for this BCL. -using System.Runtime.CompilerServices; using System.Diagnostics.Contracts; -using System.Drawing; namespace System { @@ -30,8 +28,14 @@ namespace System /// public static class MathF { + /// + /// Represents the ratio of the circumference of a circle to its diameter, specified by the constant, p. + /// public const float PI = 3.14159265f; + /// + /// Represents the natural logarithmic base, specified by the constant, e. + /// public const float E = 2.71828183f; private static float NegativeZero = Int32BitsToSingle(unchecked((int)0x80000000)); From 2f2bf2e8ebe55ab948da84faf549927c4aeb9f2e Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Fri, 25 Aug 2023 11:54:15 -0600 Subject: [PATCH 07/10] minor csproj fixes --- .../src/Microsoft.Bcl.Numerics.csproj | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj index 8a44f05557c49..8812409ce96b4 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -14,7 +14,6 @@ - true true @@ -26,12 +25,4 @@ - - - - - - - - From 3a77444c7113a8b9ffe3d87016d4eb3fbf7e397d Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Fri, 25 Aug 2023 11:56:56 -0600 Subject: [PATCH 08/10] fixed ref target frameworks --- .../Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj index 1bf08ede702ff..52b47cda6ada2 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj @@ -1,7 +1,7 @@ - $(NetCoreAppCurrent);netstandard2.0;netstandard2.1;$(NetFrameworkMinimum) + netstandard2.0;$(NetFrameworkMinimum);netstandard2.1 From 10b71066f00b533ea78093b2b61af080aa7791ed Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Fri, 25 Aug 2023 12:01:58 -0600 Subject: [PATCH 09/10] minor ref csproj updates --- .../Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj index 52b47cda6ada2..36d3ac9605c19 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/ref/Microsoft.Bcl.Numerics.csproj @@ -5,8 +5,8 @@ - - + + From 7f489cd2788fcdb40015159014934b77c86cf015 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Fri, 25 Aug 2023 12:05:52 -0600 Subject: [PATCH 10/10] minor csproj updates --- .../src/Microsoft.Bcl.Numerics.csproj | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj index 8812409ce96b4..5d6b96dc6a29a 100644 --- a/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj +++ b/src/libraries/Microsoft.Bcl.Numerics/src/Microsoft.Bcl.Numerics.csproj @@ -2,8 +2,8 @@ netstandard2.0;$(NetFrameworkMinimum);netstandard2.1 + true true - $(NoWarn) Provides the System.MathF for .NET Standard 2.0 @@ -13,10 +13,6 @@ true - - true - -