Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
CosPi
  • Loading branch information
huoyaoyuan committed Jun 3, 2021
commit dd97080f0d55e3ed151bb06a04e98424dfe9ff41
46 changes: 46 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1503,5 +1503,51 @@ public static double SinPi(double x)
double sin = Sin(rem * PI);
return invert ? -sin : sin;
}

/// <summary>
/// Returns the cosine of the specified angle measured in half-turns.
/// </summary>
/// <param name="x">An angle, measured in half-turns.</param>
/// <returns>The cosine of <paramref name="x"/>. If <paramref name="x"/> is equal to <see cref="double.NaN"/>, <see cref="double.PositiveInfinity"/>,
/// or <see cref="double.NegativeInfinity"/>, this method returns <see cref="double.NaN"/>. </returns>
/// <remarks>
/// This method is effectively Cos(x * PI), with higher precision.
/// It guarantees to return -1, 0, or 1 when <paramref name="x"/> is integer or half-integer.
/// </remarks>
public static double CosPi(double x)
{
// Implementation based on https://github.com/boostorg/math/blob/develop/include/boost/math/special_functions/cos_pi.hpp

if (Abs(x) < 0.25)
{
return Cos(x * PI);
}

if (x < 0)
{
x = -x;
}

bool invert = false;
double floor = Floor(x);
if (((int)floor & 1) != 0)
{
invert = !invert;
}

double rem = x - floor;
if (rem > 0.5)
{
rem = 1 - rem;
invert = !invert;
}
else if (rem == 0.5)
{
return 0;
}

double cos = rem > 0.25 ? Cos(0.5 - rem) : Cos(rem);
return invert ? -cos : cos;
}
}
}
46 changes: 46 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/MathF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -573,5 +573,51 @@ public static float SinPi(float x)
float sin = Sin(rem * PI);
return invert ? -sin : sin;
}

/// <summary>
/// Returns the cosine of the specified angle measured in half-turns.
/// </summary>
/// <param name="x">An angle, measured in half-turns.</param>
/// <returns>The cosine of <paramref name="x"/>. If <paramref name="x"/> is equal to <see cref="float.NaN"/>, <see cref="double.PositiveInfinity"/>,
/// or <see cref="float.NegativeInfinity"/>, this method returns <see cref="float.NaN"/>. </returns>
/// <remarks>
/// This method is effectively Cos(x * PI), with higher precision.
/// It guarantees to return -1, 0, or 1 when <paramref name="x"/> is integer or half-integer.
/// </remarks>
public static float CosPi(float x)
{
// Implementation based on https://github.com/boostorg/math/blob/develop/include/boost/math/special_functions/cos_pi.hpp

if (Abs(x) < 0.25f)
{
return Cos(x * PI);
}

if (x < 0)
{
x = -x;
}

bool invert = false;
float floor = Floor(x);
if (((int)floor & 1) != 0)
{
invert = !invert;
}

float rem = x - floor;
if (rem > 0.5f)
{
rem = 1 - rem;
invert = !invert;
}
else if (rem == 0.5f)
{
return 0;
}

float cos = rem > 0.25f ? Cos(0.5f - rem) : Cos(rem);
return invert ? -cos : cos;
}
}
}
36 changes: 36 additions & 0 deletions src/libraries/System.Runtime.Extensions/tests/System/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3212,5 +3212,41 @@ public static void SinPi_Float_Precision()
Assert.Equal(0, MathF.SinPi(0.6789f) + MathF.SinPi(-0.6789f));
Assert.Equal(0, MathF.SinPi(1.2345f) + MathF.SinPi(-1.2345f));
}

[Fact]
public static void CosPi_Double_Precision()
{
Assert.Equal( 1, Math.CosPi( 0.0));
Assert.Equal( 0, Math.CosPi( 0.5));
Assert.Equal( 0, Math.CosPi(-0.5));
Assert.Equal(-1, Math.CosPi( 1.0));
Assert.Equal(-1, Math.CosPi(-1.0));
Assert.Equal( 0, Math.CosPi( 1.5));
Assert.Equal( 0, Math.CosPi(-1.5));
Assert.Equal( 1, Math.CosPi( 2.0));
Assert.Equal( 1, Math.CosPi(-2.0));

Assert.Equal(0, Math.CosPi(0.1234) - Math.CosPi(-0.1234));
Assert.Equal(0, Math.CosPi(0.6789) - Math.CosPi(-0.6789));
Assert.Equal(0, Math.CosPi(1.2345) - Math.CosPi(-1.2345));
}

[Fact]
public static void CosPi_Float_Precision()
{
Assert.Equal( 1, MathF.CosPi( 0.0f));
Assert.Equal( 0, MathF.CosPi( 0.5f));
Assert.Equal( 0, MathF.CosPi(-0.5f));
Assert.Equal(-1, MathF.CosPi( 1.0f));
Assert.Equal(-1, MathF.CosPi(-1.0f));
Assert.Equal( 0, MathF.CosPi( 1.5f));
Assert.Equal( 0, MathF.CosPi(-1.5f));
Assert.Equal( 1, MathF.CosPi( 2.0f));
Assert.Equal( 1, MathF.CosPi(-2.0f));

Assert.Equal(0, MathF.CosPi(0.1234f) - MathF.CosPi(-0.1234f));
Assert.Equal(0, MathF.CosPi(0.6789f) - MathF.CosPi(-0.6789f));
Assert.Equal(0, MathF.CosPi(1.2345f) - MathF.CosPi(-1.2345f));
}
}
}
6 changes: 4 additions & 2 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2786,6 +2786,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; }
Expand Down Expand Up @@ -2873,9 +2874,9 @@ public static partial class Math
public static int Sign(sbyte value) { throw null; }
public static int Sign(float value) { throw null; }
public static double Sin(double a) { throw null; }
public static double SinPi(double x) { 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; }
Expand All @@ -2902,6 +2903,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; }
Expand All @@ -2925,9 +2927,9 @@ public static partial class MathF
public static float ScaleB(float x, int n) { throw null; }
public static int Sign(float x) { throw null; }
public static float Sin(float x) { throw null; }
public static float SinPi(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; }
Expand Down