CSharp · Console
using System;
public class Program
{
public static void Main()
{
Console.WriteLine(bessel_k(1,2));
}
public static double bessel_k(double v, double x)
{
if (x <= 0)
{
throw new ArgumentOutOfRangeException("x", "Value must be greater than 0");
}
return bessel_ik(v, x);
}
private static double bessel_ik(double v, double x)
{
double u, Kv, Kv1, Ku, Ku1, W, current, prev, next;
bool reflect = false;
uint n, k;
if (v < 0)
{
reflect = true;
v = -v;
}
n = (uint)Math.Round(v);
u = v - n;
W = 1 / x;
CF2_ik(u, x, out Ku, out Ku1);
prev = Ku;
current = Ku1;
double scale = 1;
for (k = 1; k <= n; k++)
{
double fact = 2 * (u + k) / x;
if ((Double.MaxValue - Math.Abs(prev)) / fact < Math.Abs(current))
{
prev /= current;
scale /= current;
current = 1;
}
next = fact * current + prev;
prev = current;
current = next;
}
Kv = prev;
Kv1 = current;
if (reflect)
{
double z = (u + n % 2);
double fact = (2 / Math.PI) * (sin_pi(z) * Kv);
if (Double.MaxValue * scale < fact)
{
throw new ArgumentOutOfRangeException("fact", "Error. Calculation exceeds Double.MaxValue");
}
}
if (Double.MaxValue * scale < Kv)
{
throw new ArgumentOutOfRangeException("fact", "Error. Calculation exceeds Double.MaxValue");
}
return Kv / scale;
}
static double sin_pi(double x)
{
if (x < 0)
{
return -sin_pi(-x);
}
bool invert;
if (x < 0.5)
{
return Math.Sin(Math.PI * x);
}
if (x < 1)
{
invert = true;
x = -x;
}
else
{
invert = false;
}
double rem = Math.Floor(x);
if (itrunc(rem) == 1)
{
invert = !invert;
}
rem = x - rem;
if (rem > 0.5f)
{
rem = 1 - rem;
}
if (rem == 0.5f)
{
return (double)(invert ? -1 : 1);
}
rem = Math.Sin(Math.PI * rem);
return invert ? -rem : rem;
}
static int itrunc(double v)
{
double r = Math.Truncate(v);
if ((Math.Abs(r)) > (Int64.MaxValue))
{
throw new ArgumentOutOfRangeException("r", "Error. Calculation exceeds Int64.MaxValue");
}
return (int)(r);
}
static int CF2_ik(double v, double x, out double Kv, out double Kv1)
{
double S, C, Q, D, f, a, b, q, delta, tolerance, current, prev;
ulong k;
tolerance = Double.Epsilon;
a = v * v - 0.25f;
b = 2 * (x + 1);
D = 1 / b;
f = delta = D;
prev = 0;
current = 1;
Q = C = -a;
S = 1 + Q * delta;
for (k = 2; k < 50; k++)
{
a -= 2 * (k - 1);
b += 2;
D = 1 / (b + a * D);
delta *= b * D - 1;
f += delta;
q = (prev - (b - 2) * current) / a;
prev = current;
current = q;
C *= -a / k;
Q += C * q;
S += Q * delta;
if (q < Double.Epsilon)
{
C *= q;
prev /= q;
current /= q;
q = 1;
}
if (Math.Abs(Q * delta) < Math.Abs(S) * tolerance)
{
break;
}
}
if (x >= Math.Log(Double.MaxValue))
{
Kv = Math.Exp(0.5f * Math.Log(Math.PI / (2 * x)) - x - Math.Log(S));
}
else
{
Kv = Math.Sqrt(Math.PI / (2 * x)) * Math.Exp(-x) / S;
}
Kv1 = Kv * (0.5f + v + x + (v * v - 0.25f) * f) / x;
return 0;
}
}