diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs
index c215d7a68ef259..3dc95c6bec2de4 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Math.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs
@@ -1449,5 +1449,239 @@ public static double ScaleB(double x, int n)
double u = BitConverter.Int64BitsToDouble(((long)(0x3ff + n) << 52));
return y * u;
}
+
+ ///
+ /// Returns the sine of the specified angle measured in half-revolutions.
+ ///
+ /// An angle, measured in half-revolutions.
+ /// The sine of . If is equal to , ,
+ /// or , this method returns .
+ ///
+ /// This method is effectively Sin(x * PI), with higher precision.
+ /// It guarantees to return -1, 0, or 1 when is integer or half-integer.
+ ///
+ public static double SinPi(double x)
+ {
+ if (Abs(x) < 0.5 || !double.IsFinite(x))
+ {
+ // Fast path for small/special values, also covers +0/-0
+ return Sin(x * PI);
+ }
+
+ bool invert = false;
+ if (x < 0)
+ {
+ x = -x;
+ invert = true;
+ }
+
+ double floor = Floor(x);
+ if (x == floor)
+ {
+ // +0 for +n and -0 for -n
+ return invert ? -0.0 : 0.0;
+ }
+
+ // fold all input into (0, 0.5]
+ if (((long)floor & 1) != 0)
+ {
+ // sin(x + PI) = -sin(x)
+ invert = !invert;
+ }
+
+ double rem = x - floor;
+ if (rem == 0.5)
+ {
+ return invert ? -1 : 1;
+ }
+
+ if (rem > 0.5)
+ {
+ // sin(PI - x) = sin(x)
+ rem = 1 - rem;
+ }
+
+ double sin = Sin(rem * PI);
+ return invert ? -sin : sin;
+ }
+
+ ///
+ /// Returns the cosine of the specified angle measured in half-revolutions.
+ ///
+ /// An angle, measured in half-revolutions.
+ /// The cosine of . If is equal to , ,
+ /// or , this method returns .
+ ///
+ /// This method is effectively Cos(x * PI), with higher precision.
+ /// It guarantees to return -1, 0, or 1 when is integer or half-integer.
+ ///
+ public static double CosPi(double x)
+ {
+ if (Abs(x) < 0.5 || !double.IsFinite(x))
+ {
+ // Fast path for small/special values, also covers +0/-0
+ return Cos(x * PI);
+ }
+
+ bool invert = false;
+ if (x < 0)
+ {
+ x = -x;
+ }
+
+ double floor = Floor(x);
+
+ // fold all input into [0, 0.5]
+ if (((long)floor & 1) != 0)
+ {
+ // cos(x + PI) = -cos(x)
+ invert = !invert;
+ }
+
+ if (x == floor)
+ {
+ return invert ? -1 : 1;
+ }
+
+ double rem = x - floor;
+ if (rem == 0.5)
+ {
+ return 0.0;
+ }
+
+ if (rem > 0.5)
+ {
+ // cos(PI - x) = -cos(x)
+ rem = 1 - rem;
+ invert = !invert;
+ }
+
+ double cos = Cos(rem * PI);
+ return invert ? -cos : cos;
+ }
+
+ ///
+ /// Returns the tangent of the specified angle measured in half-revolutions.
+ ///
+ /// An angle, measured in half-revolutions.
+ /// The tangent of . If is equal to , ,
+ /// or , this method returns .
+ ///
+ /// This method is effectively Tan(x * PI), with higher precision.
+ /// It guarantees to return 0, or when is integer or half-integer.
+ ///
+ public static double TanPi(double x)
+ {
+ if (Abs(x) < 0.5 || !double.IsFinite(x))
+ {
+ // Fast path for small/special values, also covers +0/-0
+ return Tan(x * PI);
+ }
+
+ bool invert = false;
+ if (x < 0)
+ {
+ x = -x;
+ invert = true;
+ }
+
+ double floor = Floor(x);
+ if (x == floor)
+ {
+ // +0 for +2n and -0 for +2n+1
+ // -0 for -2n and +0 for -2n-1
+ if (((long)floor & 1) != 0)
+ {
+ invert = !invert;
+ }
+ return invert ? -0.0 : 0.0;
+ }
+
+ // fold all input into (0, 0.5]
+ double rem = x - floor;
+ if (rem == 0.5)
+ {
+ // +inf for +2n+0.5 and -inf for +2n+1.5
+ // -inf for -2n-0.5 and +inf for -2n-1.5
+ if (((long)floor & 1) != 0)
+ {
+ invert = !invert;
+ }
+ return invert ? double.NegativeInfinity : double.PositiveInfinity;
+ }
+
+ if (rem > 0.5)
+ {
+ // tan(PI - x) = -tan(x)
+ rem = 1 - rem;
+ invert = !invert;
+ }
+
+ double tan = Tan(rem * PI);
+ return invert ? -tan : tan;
+ }
+
+ // Double inverse-trigs pass all special value tests on all platforms.
+ // Keep them fast.
+
+ ///
+ /// Returns the angle measured in half-revolutions whose sine is the specified number.
+ ///
+ /// A number representing a sine, where must be greater than or equal to -1, but
+ /// less than or equal to 1.
+ /// An angle, θ, measured in half-revolutions, such that -0.5 ≤ θ ≤ 0.5.
+ /// -or-
+ /// if < -1 or > 1
+ /// or equals .
+ public static double AsinPi(double x) => Asin(x) / PI;
+
+ ///
+ /// Returns the angle measured in half-revolutions whose cosine is the specified number.
+ ///
+ /// A number representing a cosine, where must be greater than or equal to -1, but
+ /// less than or equal to 1.
+ /// An angle, θ, measured in half-revolutions, such that -0.5 ≤ θ ≤ 0.5.
+ /// -or-
+ /// if < -1 or > 1
+ /// or equals .
+ public static double AcosPi(double x) => Acos(x) / PI;
+
+ ///
+ /// Returns the angle measured in half-revolutions whose tangent is the specified number.
+ ///
+ /// A number representing a tangent.
+ /// An angle, θ, measured in half-revolutions, such that -0.5 ≤ θ ≤ 0.5.
+ /// -or-
+ /// if equals ,
+ /// -0.5 if equals ,
+ /// or 0.5 if equals .
+ public static double AtanPi(double x) => Atan(x) / PI;
+
+ ///
+ /// Returns the angle whose measured in half-revolutions tangent is the quotient of two specified numbers.
+ ///
+ /// The y coordinate of a point.
+ /// The x coordinate of a point.
+ /// An angle, θ, measured in half-revolutions, such that -1 ≤ θ ≤ 1, and tan(θ) = y / x,
+ /// where (x, y) is a point in the Cartesian plane. Observe the following:
+ ///
+ /// - For (x, y) in quadrant 1, 0 < θ < 0.5.
+ /// - For (x, y) in quadrant 2, 0.5 < θ ≤ 1.
+ /// - For (x, y) in quadrant 3, -1 < θ < -0.5.
+ /// - For (x, y) in quadrant 4, -0.5 < θ < 0.
+ ///
+ /// For points on the boundaries of the quadrants, the return value is the following:
+ ///
+ /// - If y is 0 and x is not negative, θ = 0.
+ /// - If y is 0 and x is negative, θ = 1.
+ /// - If y is positive and x is 0, θ = 0.5.
+ /// - If y is negative and x is 0, θ = -0.5.
+ /// - If y is 0 and x is 0, θ = 0.
+ /// - If y is 0 and x is 0, θ = 0.
+ ///
+ /// If x or y is , or if x and y are either
+ /// or ,
+ /// the method returns .
+ public static double Atan2Pi(double y, double x) => Atan2(y, x) / PI;
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs
index 0050f5d43368cc..26ab3c680d4ad3 100644
--- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs
@@ -519,5 +519,286 @@ public static float ScaleB(float x, int n)
float u = BitConverter.Int32BitsToSingle(((int)(0x7f + n) << 23));
return y * u;
}
+
+ ///
+ /// Returns the sine of the specified angle measured in half-revolutions.
+ ///
+ /// An angle, measured in half-revolutions.
+ /// The sine of . If is equal to , ,
+ /// or , this method returns .
+ ///
+ /// This method is effectively Sin(x * PI), with higher precision.
+ /// It guarantees to return -1, 0, or 1 when is integer or half-integer.
+ ///
+ public static float SinPi(float x)
+ {
+ if (Abs(x) < 0.5f || !float.IsFinite(x))
+ {
+ // Fast path for small/special values, also covers +0/-0
+ return Sin(x * PI);
+ }
+
+ bool invert = false;
+ if (x < 0)
+ {
+ x = -x;
+ invert = true;
+ }
+
+ float floor = Floor(x);
+ if (x == floor)
+ {
+ // +0 for +n and -0 for -n
+ return invert ? -0.0f : 0.0f;
+ }
+
+ // fold all input into (0, 0.5]
+ if (((int)floor & 1) != 0)
+ {
+ // sin(x + PI) = -sin(x)
+ invert = !invert;
+ }
+
+ float rem = x - floor;
+ if (rem == 0.5f)
+ {
+ return invert ? -1 : 1;
+ }
+
+ if (rem > 0.5f)
+ {
+ // sin(PI - x) = sin(x)
+ rem = 1 - rem;
+ }
+
+ float sin = Sin(rem * PI);
+ return invert ? -sin : sin;
+ }
+
+ ///
+ /// Returns the cosine of the specified angle measured in half-revolutions.
+ ///
+ /// An angle, measured in half-revolutions.
+ /// The cosine of . If is equal to , ,
+ /// or , this method returns .
+ ///
+ /// This method is effectively Cos(x * PI), with higher precision.
+ /// It guarantees to return -1, 0, or 1 when is integer or half-integer.
+ ///
+ public static float CosPi(float x)
+ {
+ if (Abs(x) < 0.5f || !float.IsFinite(x))
+ {
+ // Fast path for small/special values, also covers +0/-0
+ return Cos(x * PI);
+ }
+
+ bool invert = false;
+ if (x < 0)
+ {
+ x = -x;
+ }
+
+ float floor = Floor(x);
+
+ // fold all input into [0, 0.5]
+ if (((int)floor & 1) != 0)
+ {
+ // cos(x + PI) = -cos(x)
+ invert = !invert;
+ }
+
+ if (x == floor)
+ {
+ return invert ? -1 : 1;
+ }
+
+ float rem = x - floor;
+ if (rem == 0.5f)
+ {
+ return 0.0f;
+ }
+
+ if (rem > 0.5f)
+ {
+ // cos(PI - x) = -cos(x)
+ rem = 1 - rem;
+ invert = !invert;
+ }
+
+ float cos = Cos(rem * PI);
+ return invert ? -cos : cos;
+ }
+
+ ///
+ /// Returns the tangent of the specified angle measured in half-revolutions.
+ ///
+ /// An angle, measured in half-revolutions.
+ /// The tangent of . If is equal to , ,
+ /// or , this method returns .
+ ///
+ /// This method is effectively Tan(x * PI), with higher precision.
+ /// It guarantees to return 0, or when is integer or half-integer.
+ ///
+ public static float TanPi(float x)
+ {
+
+ if (Abs(x) < 0.5f || !float.IsFinite(x))
+ {
+ // Fast path for small/special values, also covers +0/-0
+ return Tan(x * PI);
+ }
+
+ bool invert = false;
+ if (x < 0)
+ {
+ x = -x;
+ invert = true;
+ }
+
+ float floor = Floor(x);
+ if (x == floor)
+ {
+ // +0 for +2n and -0 for +2n+1
+ // -0 for -2n and +0 for -2n-1
+ if (((int)floor & 1) != 0)
+ {
+ invert = !invert;
+ }
+ return invert ? -0.0f : 0.0f;
+ }
+
+ // fold all input into (0, 0.5]
+ float rem = x - floor;
+ if (rem == 0.5f)
+ {
+ // +inf for +2n+0.5 and -inf for +2n+1.5
+ // -inf for -2n-0.5 and +inf for -2n-1.5
+ if (((long)floor & 1) != 0)
+ {
+ invert = !invert;
+ }
+ return invert ? float.NegativeInfinity : float.PositiveInfinity;
+ }
+
+ if (rem > 0.5)
+ {
+ // tan(PI - x) = -tan(x)
+ rem = 1 - rem;
+ invert = !invert;
+ }
+
+ float tan = Tan(rem * PI);
+ return invert ? -tan : tan;
+ }
+
+ // Float inverse-trigs fail special value tests on some platforms.
+ // Special case them.
+
+ ///
+ /// Returns the angle measured in half-revolutions whose sine is the specified number.
+ ///
+ /// A number representing a sine, where must be greater than or equal to -1, but
+ /// less than or equal to 1.
+ /// An angle, θ, measured in half-revolutions, such that -0.5 ≤ θ ≤ 0.5.
+ /// -or-
+ /// if < -1 or > 1
+ /// or equals .
+ public static float AsinPi(float x)
+ {
+ if (x == 1)
+ {
+ return 0.5f;
+ }
+ if (x == -1)
+ {
+ return -0.5f;
+ }
+
+ return Asin(x) / PI;
+ }
+
+ ///
+ /// Returns the angle measured in half-revolutions whose cosine is the specified number.
+ ///
+ /// A number representing a cosine, where must be greater than or equal to -1, but
+ /// less than or equal to 1.
+ /// An angle, θ, measured in half-revolutions, such that -0.5 ≤ θ ≤ 0.5.
+ /// -or-
+ /// if < -1 or > 1
+ /// or equals .
+ public static float AcosPi(float x)
+ {
+ if (x == 0)
+ {
+ return 0.5f;
+ }
+
+ return x > 0 ? Acos(x) / PI : 1 - Acos(-x) / PI;
+ }
+
+ ///
+ /// Returns the angle measured in half-revolutions whose tangent is the specified number.
+ ///
+ /// A number representing a tangent.
+ /// An angle, θ, measured in half-revolutions, such that -0.5 ≤ θ ≤ 0.5.
+ /// -or-
+ /// if equals ,
+ /// -0.5 if equals ,
+ /// or 0.5 if equals .
+ public static float AtanPi(float x)
+ {
+ if (float.IsPositiveInfinity(x))
+ {
+ return 0.5f;
+ }
+ else if (float.IsNegativeInfinity(x))
+ {
+ return -0.5f;
+ }
+ else
+ {
+ return Atan(x) / PI;
+ }
+ }
+
+ ///
+ /// Returns the angle whose measured in half-revolutions tangent is the quotient of two specified numbers.
+ ///
+ /// The y coordinate of a point.
+ /// The x coordinate of a point.
+ /// An angle, θ, measured in half-revolutions, such that -1 ≤ θ ≤ 1, and tan(θ) = y / x,
+ /// where (x, y) is a point in the Cartesian plane. Observe the following:
+ ///
+ /// - For (x, y) in quadrant 1, 0 < θ < 0.5.
+ /// - For (x, y) in quadrant 2, 0.5 < θ ≤ 1.
+ /// - For (x, y) in quadrant 3, -1 < θ < -0.5.
+ /// - For (x, y) in quadrant 4, -0.5 < θ < 0.
+ ///
+ /// For points on the boundaries of the quadrants, the return value is the following:
+ ///
+ /// - If y is 0 and x is not negative, θ = 0.
+ /// - If y is 0 and x is negative, θ = 1.
+ /// - If y is positive and x is 0, θ = 0.5.
+ /// - If y is negative and x is 0, θ = -0.5.
+ /// - If y is 0 and x is 0, θ = 0.
+ /// - If y is 0 and x is 0, θ = 0.
+ ///
+ /// If x or y is , or if x and y are either
+ /// or ,
+ /// the method returns .
+ public static float Atan2Pi(float y, float x)
+ {
+ float atan = Atan2(y, x) / PI;
+
+ // if x or y is 0 or inf, it's a special value required by IEEE754:2019
+ // rounding to nearist quarter-integer (keeps +0/-0)
+ if (x == 0 || y == 0 || float.IsInfinity(x) || float.IsInfinity(y))
+ {
+ return Round(atan * 4) / 4;
+ }
+
+ return atan;
+ }
}
}
diff --git a/src/libraries/System.Runtime.Extensions/tests/System/Math.cs b/src/libraries/System.Runtime.Extensions/tests/System/Math.cs
index fbe995267afea0..482ae3d190c7dc 100644
--- a/src/libraries/System.Runtime.Extensions/tests/System/Math.cs
+++ b/src/libraries/System.Runtime.Extensions/tests/System/Math.cs
@@ -3176,5 +3176,237 @@ public static void Round_Float_Constant_Arg()
Assert.Equal( 4, MathF.Round( 3.5f, MidpointRounding.AwayFromZero));
Assert.Equal(-4, MathF.Round(-3.5f, MidpointRounding.AwayFromZero));
}
+
+ [Fact]
+ public static void SinPi_Double_Precision()
+ {
+ AssertEqual( 0.0, Math.SinPi( 0.0), 0.0);
+ AssertEqual(-0.0, Math.SinPi(-0.0), 0.0);
+ AssertEqual( 1.0, Math.SinPi( 0.5), 0.0);
+ AssertEqual(-1.0, Math.SinPi(-0.5), 0.0);
+ AssertEqual( 0.0, Math.SinPi( 1.0), 0.0);
+ AssertEqual(-0.0, Math.SinPi(-1.0), 0.0);
+ AssertEqual(-1.0, Math.SinPi( 1.5), 0.0);
+ AssertEqual( 1.0, Math.SinPi(-1.5), 0.0);
+ AssertEqual( 0.0, Math.SinPi( 2.0), 0.0);
+ AssertEqual(-0.0, Math.SinPi(-2.0), 0.0);
+
+ AssertEqual(0.0, Math.SinPi(0.1234) + Math.SinPi(-0.1234), 0.0);
+ AssertEqual(0.0, Math.SinPi(0.6789) + Math.SinPi(-0.6789), 0.0);
+ AssertEqual(0.0, Math.SinPi(1.2345) + Math.SinPi(-1.2345), 0.0);
+ }
+
+ [Fact]
+ public static void SinPi_Float_Precision()
+ {
+ AssertEqual( 0.0f, MathF.SinPi( 0.0f), 0.0f);
+ AssertEqual(-0.0f, MathF.SinPi(-0.0f), 0.0f);
+ AssertEqual( 1.0f, MathF.SinPi( 0.5f), 0.0f);
+ AssertEqual(-1.0f, MathF.SinPi(-0.5f), 0.0f);
+ AssertEqual( 0.0f, MathF.SinPi( 1.0f), 0.0f);
+ AssertEqual(-0.0f, MathF.SinPi(-1.0f), 0.0f);
+ AssertEqual(-1.0f, MathF.SinPi( 1.5f), 0.0f);
+ AssertEqual( 1.0f, MathF.SinPi(-1.5f), 0.0f);
+ AssertEqual( 0.0f, MathF.SinPi( 2.0f), 0.0f);
+ AssertEqual(-0.0f, MathF.SinPi(-2.0f), 0.0f);
+
+ AssertEqual(0.0f, MathF.SinPi(0.1234f) + MathF.SinPi(-0.1234f), 0.0f);
+ AssertEqual(0.0f, MathF.SinPi(0.6789f) + MathF.SinPi(-0.6789f), 0.0f);
+ AssertEqual(0.0f, MathF.SinPi(1.2345f) + MathF.SinPi(-1.2345f), 0.0f);
+ }
+
+ [Fact]
+ public static void CosPi_Double_Precision()
+ {
+ AssertEqual( 1.0, Math.CosPi( 0.0), 0.0);
+ AssertEqual( 1.0, Math.CosPi(-0.0), 0.0);
+ AssertEqual( 0.0, Math.CosPi( 0.5), 0.0);
+ AssertEqual( 0.0, Math.CosPi(-0.5), 0.0);
+ AssertEqual(-1.0, Math.CosPi( 1.0), 0.0);
+ AssertEqual(-1.0, Math.CosPi(-1.0), 0.0);
+ AssertEqual( 0.0, Math.CosPi( 1.5), 0.0);
+ AssertEqual( 0.0, Math.CosPi(-1.5), 0.0);
+ AssertEqual( 1.0, Math.CosPi( 2.0), 0.0);
+ AssertEqual( 1.0, Math.CosPi(-2.0), 0.0);
+
+ AssertEqual(0.0, Math.CosPi(0.1234) - Math.CosPi(-0.1234), 0.0);
+ AssertEqual(0.0, Math.CosPi(0.6789) - Math.CosPi(-0.6789), 0.0);
+ AssertEqual(0.0, Math.CosPi(1.2345) - Math.CosPi(-1.2345), 0.0);
+ }
+
+ [Fact]
+ public static void CosPi_Float_Precision()
+ {
+ AssertEqual( 1.0f, MathF.CosPi( 0.0f), 0.0f);
+ AssertEqual( 1.0f, MathF.CosPi(-0.0f), 0.0f);
+ AssertEqual( 0.0f, MathF.CosPi( 0.5f), 0.0f);
+ AssertEqual( 0.0f, MathF.CosPi(-0.5f), 0.0f);
+ AssertEqual(-1.0f, MathF.CosPi( 1.0f), 0.0f);
+ AssertEqual(-1.0f, MathF.CosPi(-1.0f), 0.0f);
+ AssertEqual( 0.0f, MathF.CosPi( 1.5f), 0.0f);
+ AssertEqual( 0.0f, MathF.CosPi(-1.5f), 0.0f);
+ AssertEqual( 1.0f, MathF.CosPi( 2.0f), 0.0f);
+ AssertEqual( 1.0f, MathF.CosPi(-2.0f), 0.0f);
+
+ AssertEqual(0.0f, MathF.CosPi(0.1234f) - MathF.CosPi(-0.1234f), 0.0f);
+ AssertEqual(0.0f, MathF.CosPi(0.6789f) - MathF.CosPi(-0.6789f), 0.0f);
+ AssertEqual(0.0f, MathF.CosPi(1.2345f) - MathF.CosPi(-1.2345f), 0.0f);
+ }
+
+ [Fact]
+ public static void TanPi_Double_Precision()
+ {
+ AssertEqual( 0.0, Math.TanPi( 0.0), 0.0);
+ AssertEqual( -0.0, Math.TanPi(-0.0), 0.0);
+ AssertEqual(double.PositiveInfinity, Math.TanPi( 0.5), 0.0);
+ AssertEqual(double.NegativeInfinity, Math.TanPi(-0.5), 0.0);
+ AssertEqual( -0.0, Math.TanPi( 1.0), 0.0);
+ AssertEqual( 0.0, Math.TanPi(-1.0), 0.0);
+ AssertEqual(double.NegativeInfinity, Math.TanPi( 1.5), 0.0);
+ AssertEqual(double.PositiveInfinity, Math.TanPi(-1.5), 0.0);
+ AssertEqual( 0.0, Math.TanPi( 2.0), 0.0);
+ AssertEqual( -0.0, Math.TanPi(-2.0), 0.0);
+
+ AssertEqual(0.0, Math.TanPi(0.1234) + Math.TanPi(-0.1234), 0.0);
+ AssertEqual(0.0, Math.TanPi(0.6789) + Math.TanPi(-0.6789), 0.0);
+ AssertEqual(0.0, Math.TanPi(1.2345) + Math.TanPi(-1.2345), 0.0);
+ }
+
+ [Fact]
+ public static void TanPi_Float_Precision()
+ {
+ AssertEqual( 0.0f, MathF.TanPi( 0.0f), 0.0f);
+ AssertEqual( -0.0f, MathF.TanPi(-0.0f), 0.0f);
+ AssertEqual(float.PositiveInfinity, MathF.TanPi( 0.5f), 0.0f);
+ AssertEqual(float.NegativeInfinity, MathF.TanPi(-0.5f), 0.0f);
+ AssertEqual( -0.0f, MathF.TanPi( 1.0f), 0.0f);
+ AssertEqual( 0.0f, MathF.TanPi(-1.0f), 0.0f);
+ AssertEqual(float.NegativeInfinity, MathF.TanPi( 1.5f), 0.0f);
+ AssertEqual(float.PositiveInfinity, MathF.TanPi(-1.5f), 0.0f);
+ AssertEqual( 0.0f, MathF.TanPi( 2.0f), 0.0f);
+ AssertEqual( -0.0f, MathF.TanPi(-2.0f), 0.0f);
+
+ AssertEqual(0.0f, MathF.TanPi(0.1234f) + MathF.TanPi(-0.1234f), 0.0f);
+ AssertEqual(0.0f, MathF.TanPi(0.6789f) + MathF.TanPi(-0.6789f), 0.0f);
+ AssertEqual(0.0f, MathF.TanPi(1.2345f) + MathF.TanPi(-1.2345f), 0.0f);
+ }
+
+ [Theory]
+ [InlineData(0.1234)]
+ [InlineData(0.6789)]
+ [InlineData(1.2345)]
+ [InlineData(1.9876)]
+ public static void TriPi_Double_Correctness(double x)
+ {
+ AssertEqual(Math.Sin(x * Math.PI), Math.SinPi(x), CrossPlatformMachineEpsilonForEstimates);
+ AssertEqual(Math.Cos(x * Math.PI), Math.CosPi(x), CrossPlatformMachineEpsilonForEstimates);
+ AssertEqual(Math.Tan(x * Math.PI), Math.TanPi(x), CrossPlatformMachineEpsilonForEstimates);
+ }
+
+ [Theory]
+ [InlineData(0.1234f)]
+ [InlineData(0.6789f)]
+ [InlineData(1.2345f)]
+ [InlineData(1.9876f)]
+ public static void TriPi_Float_Correctness(float x)
+ {
+ AssertEqual(MathF.Sin(x * MathF.PI), MathF.SinPi(x), (float)CrossPlatformMachineEpsilonForEstimates);
+ AssertEqual(MathF.Cos(x * MathF.PI), MathF.CosPi(x), (float)CrossPlatformMachineEpsilonForEstimates);
+ AssertEqual(MathF.Tan(x * MathF.PI), MathF.TanPi(x), (float)CrossPlatformMachineEpsilonForEstimates);
+ }
+
+ [Fact]
+ public static void AsinPi_Double_Precision()
+ {
+ AssertEqual( 0.5, Math.AsinPi( 1.0), 0.0);
+ AssertEqual(-0.5, Math.AsinPi(-1.0), 0.0);
+ }
+
+ [Fact]
+ public static void AsinPi_Float_Precision()
+ {
+ AssertEqual( 0.5f, MathF.AsinPi( 1.0f), 0.0f);
+ AssertEqual(-0.5f, MathF.AsinPi(-1.0f), 0.0f);
+ }
+
+ [Fact]
+ public static void AcosPi_Double_Precision()
+ {
+ AssertEqual( 0.5, Math.AcosPi( 0.0), 0.0);
+ AssertEqual( 0.5, Math.AcosPi(-0.0), 0.0);
+ AssertEqual( 0.0, Math.AcosPi( 1.0), 0.0);
+ AssertEqual( 1.0, Math.AcosPi(-1.0), 0.0);
+ }
+
+ [Fact]
+ public static void AcosPi_Float_Precision()
+ {
+ AssertEqual( 0.5f, MathF.AcosPi( 0.0f), 0.0f);
+ AssertEqual( 0.5f, MathF.AcosPi(-0.0f), 0.0f);
+ AssertEqual( 0.0f, MathF.AcosPi( 1.0f), 0.0f);
+ AssertEqual( 1.0f, MathF.AcosPi(-1.0f), 0.0f);
+ }
+
+ [Fact]
+ public static void AtanPi_Double_Precision()
+ {
+ AssertEqual( 0.5, Math.AtanPi(double.PositiveInfinity), 0.0);
+ AssertEqual(-0.5, Math.AtanPi(double.NegativeInfinity), 0.0);
+ }
+
+ [Fact]
+ public static void AtanPi_Float_Precision()
+ {
+ AssertEqual( 0.5f, MathF.AtanPi(float.PositiveInfinity), 0.0f);
+ AssertEqual(-0.5f, MathF.AtanPi(float.NegativeInfinity), 0.0f);
+ }
+
+ [Theory]
+ [InlineData( 0.0, -0.0, 1.0)]
+ [InlineData(-0.0, -0.0, -1.0)]
+ [InlineData( 0.0, -1.0, 1.0)]
+ [InlineData(-0.0, -1.0, -1.0)]
+ [InlineData(-1.0, 0.0, -0.5)]
+ [InlineData(-1.0, -0.0, -0.5)]
+ [InlineData( 1.0, 0.0, 0.5)]
+ [InlineData( 1.0, -0.0, 0.5)]
+ [InlineData( 1.0, double.NegativeInfinity, 1.0)]
+ [InlineData(-1.0, double.NegativeInfinity, -1.0)]
+ [InlineData(double.PositiveInfinity, 1.0, 0.5)]
+ [InlineData(double.PositiveInfinity, -1.0, 0.5)]
+ [InlineData(double.NegativeInfinity, 1.0, -0.5)]
+ [InlineData(double.NegativeInfinity, -1.0, -0.5)]
+ [InlineData(double.PositiveInfinity, double.NegativeInfinity, 0.75)]
+ [InlineData(double.NegativeInfinity, double.NegativeInfinity, -0.75)]
+ [InlineData(double.PositiveInfinity, double.PositiveInfinity, 0.25)]
+ [InlineData(double.NegativeInfinity, double.PositiveInfinity, -0.25)]
+ public static void Atan2Pi_Double_Precision(double y, double x, double expected)
+ {
+ AssertEqual(expected, Math.Atan2Pi(y, x), 0.0);
+ }
+
+ [Theory]
+ [InlineData( 0.0f, -0.0f, 1.0f)]
+ [InlineData(-0.0f, -0.0f, -1.0f)]
+ [InlineData( 0.0f, -1.0f, 1.0f)]
+ [InlineData(-0.0f, -1.0f, -1.0f)]
+ [InlineData(-1.0f, 0.0f, -0.5f)]
+ [InlineData(-1.0f, -0.0f, -0.5f)]
+ [InlineData( 1.0f, 0.0f, 0.5f)]
+ [InlineData( 1.0f, -0.0f, 0.5f)]
+ [InlineData( 1.0f, float.NegativeInfinity, 1.0f)]
+ [InlineData(-1.0f, float.NegativeInfinity, -1.0f)]
+ [InlineData(float.PositiveInfinity, 1.0f, 0.5f)]
+ [InlineData(float.PositiveInfinity, -1.0f, 0.5f)]
+ [InlineData(float.NegativeInfinity, 1.0f, -0.5f)]
+ [InlineData(float.NegativeInfinity, -1.0f, -0.5f)]
+ [InlineData(float.PositiveInfinity, float.NegativeInfinity, 0.75f)]
+ [InlineData(float.NegativeInfinity, float.NegativeInfinity, -0.75f)]
+ [InlineData(float.PositiveInfinity, float.PositiveInfinity, 0.25f)]
+ [InlineData(float.NegativeInfinity, float.PositiveInfinity, -0.25f)]
+ public static void Atan2Pi_Float_Precision(float y, float x, float expected)
+ {
+ AssertEqual(expected, MathF.Atan2Pi(y, x), 0.0f);
+ }
}
}
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index ba30ccf66a0aa9..56ab5e7c211f8d 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -2751,11 +2751,15 @@ public static partial class Math
public static float Abs(float value) { throw null; }
public static double Acos(double d) { throw null; }
public static double Acosh(double d) { throw null; }
+ public static double AcosPi(double x) { throw null; }
public static double Asin(double d) { throw null; }
public static double Asinh(double d) { throw null; }
+ public static double AsinPi(double x) { throw null; }
public static double Atan(double d) { throw null; }
public static double Atan2(double y, double x) { throw null; }
+ public static double Atan2Pi(double y, double x) { throw null; }
public static double Atanh(double d) { throw null; }
+ public static double AtanPi(double x) { throw null; }
public static long BigMul(int a, int b) { throw null; }
public static long BigMul(long a, long b, out long low) { throw null; }
[System.CLSCompliantAttribute(false)]
@@ -2786,6 +2790,7 @@ public static partial class Math
public static double CopySign(double x, double y) { throw null; }
public static double Cos(double d) { throw null; }
public static double Cosh(double value) { throw null; }
+ public static double CosPi(double x) { throw null; }
public static int DivRem(int a, int b, out int result) { throw null; }
public static long DivRem(long a, long b, out long result) { throw null; }
public static (byte Quotient, byte Remainder) DivRem(byte left, byte right) { throw null; }
@@ -2875,9 +2880,11 @@ public static partial class Math
public static double Sin(double a) { throw null; }
public static (double Sin, double Cos) SinCos(double x) { throw null; }
public static double Sinh(double value) { throw null; }
+ public static double SinPi(double x) { throw null; }
public static double Sqrt(double d) { throw null; }
public static double Tan(double a) { throw null; }
public static double Tanh(double value) { throw null; }
+ public static double TanPi(double x) { throw null; }
public static decimal Truncate(decimal d) { throw null; }
public static double Truncate(double d) { throw null; }
}
@@ -2889,11 +2896,15 @@ public static partial class MathF
public static float Abs(float x) { throw null; }
public static float Acos(float x) { throw null; }
public static float Acosh(float x) { throw null; }
+ public static float AcosPi(float x) { throw null; }
public static float Asin(float x) { throw null; }
public static float Asinh(float x) { throw null; }
+ public static float AsinPi(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 Atan2Pi(float y, float x) { throw null; }
public static float Atanh(float x) { throw null; }
+ public static float AtanPi(float x) { throw null; }
public static float BitDecrement(float x) { throw null; }
public static float BitIncrement(float x) { throw null; }
public static float Cbrt(float x) { throw null; }
@@ -2901,6 +2912,7 @@ public static partial class MathF
public static float CopySign(float x, float y) { throw null; }
public static float Cos(float x) { throw null; }
public static float Cosh(float x) { throw null; }
+ public static float CosPi(float x) { throw null; }
public static float Exp(float x) { throw null; }
public static float Floor(float x) { throw null; }
public static float FusedMultiplyAdd(float x, float y, float z) { throw null; }
@@ -2926,9 +2938,11 @@ public static partial class MathF
public static float Sin(float x) { throw null; }
public static (float Sin, float Cos) SinCos(float x) { throw null; }
public static float Sinh(float x) { throw null; }
+ public static float SinPi(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 TanPi(float x) { throw null; }
public static float Truncate(float x) { throw null; }
}
public partial class MemberAccessException : System.SystemException