Code:
static double f(double x, int klimit)
{
double result = Double.NaN;
double numerator, denominator;
int k;
if (Math.Abs(x) < 1)
{
result = 0;
for (k = 0; k <= klimit; k++)
{
numerator = Math.Pow(-1, k) * Math.Pow(x, 1 + (2 * k));
denominator = 1 + (2 * k);
result += (numerator / denominator);
}
}
else if (Math.Abs(x) > 1)
{
result = 0;
for (k = 0; k <= klimit; k++)
{
numerator = Math.Pow(-1, k) * Math.Pow(x, (-1) - (2 * k));
denominator = 1 + (2 * k);
result += (numerator / denominator);
}
numerator = Math.PI * Math.Sqrt(x * x);
denominator = x * 2;
result = (numerator / denominator) - result;
}
else // x == 1
{
return 0.25 * Math.PI;
}
return result;
}
Code:
static double finv(double x, int klimit)
{
Func<int, int> factorial = (n) =>
{
int num = 1;
for (int j = n; j > 0; j--)
num *= j;
return num;
};
Func<double, int, double> g = (gx, gklimit) =>
{
double gres = 0;
double gnum, gdenom;
for (int gk = 0; gk <= gklimit; gk++)
{
gnum = Math.Pow(-1, gk) * Math.Pow(gx, (2 * gk));
gdenom = factorial(2 * gk);
gres += (gnum / gdenom);
}
return gres;
};
Func<double, int, double> h = (hx, hklimit) =>
{
double hres = 0;
double hnum, hdenom;
for (int hk = 0; hk <= hklimit; hk++)
{
hnum = Math.Pow(-1, hk) * Math.Pow(hx, (2 * hk) + 1);
hdenom = factorial((2 * hk) + 1);
hres += (hnum / hdenom);
}
return hres;
};
return (h(2 * x, klimit) / (g(2 * x, klimit) + 1));
}
Code:
finv( f ( x , k ) , k )
Well, not the exact result, but as k (klimit) increases, accuracy increases.
How's this relevant to CO?
Well, if we build on the f() function a bit we can do this...
Code:
static double f2(double y, double x, int klimit)
{
if (x > 0)
return f(y / x, klimit);
else if (y >= 0 && x < 0)
return Math.PI + f(y / x, klimit);
else if (y < 0 && x < 0)
return (-Math.PI) + f(y / x, klimit);
else if (y > 0 && x == 0)
return Math.PI / 2;
else if (y < 0 && x == 0)
return (-Math.PI) / 2;
return Double.NaN;
}
Code:
static int GetAngle(int X1, int Y1, int X2, int Y2)
{
return (int)Math.Round(f2(Y2 - Y1, X2 - X1, 5) * 180 / Math.PI);
}






