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
Add real implementation for TanPi
  • Loading branch information
huoyaoyuan committed Jun 4, 2021
commit 9d2576a50c0406886c025ae67b5c8186ede0ba87
51 changes: 50 additions & 1 deletion src/libraries/System.Private.CoreLib/src/System/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1570,6 +1570,55 @@ public static double CosPi(double x)
/// This method is effectively Tan(x * PI), with higher precision.
/// It guarantees to return 0, <see cref="double.PositiveInfinity"/> or <see cref="double.NegativeInfinity"/> when <paramref name="x"/> is integer or half-integer.
/// </remarks>
public static double TanPi(double x) => SinPi(x) / CosPi(x);
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;
}
}
}
54 changes: 52 additions & 2 deletions src/libraries/System.Private.CoreLib/src/System/MathF.cs
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ public static float SinPi(float x)
/// </remarks>
public static float CosPi(float x)
{
if (Abs(x) < 0.5f || !double.IsFinite(x))
if (Abs(x) < 0.5f || !float.IsFinite(x))
{
// Fast path for small/special values, also covers +0/-0
return Cos(x * PI);
Expand Down Expand Up @@ -640,6 +640,56 @@ public static float CosPi(float x)
/// This method is effectively Tan(x * PI), with higher precision.
/// It guarantees to return 0, <see cref="float.PositiveInfinity"/> or <see cref="float.NegativeInfinity"/> when <paramref name="x"/> is integer or half-integer.
/// </remarks>
public static float TanPi(float x) => SinPi(x) / CosPi(x);
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;
}
}
}