一般・特殊関数ライブラリ



[ 簡単な説明 ]

比較的よく使用される関数を準備しました。各関数の計算結果は関数の戻り値です。

異常な引数を与えた場合には、エラーメッセージを表示します。(プログラムは停止しません。)
この場合、戻り値は保証されません。(各関数の異状時の戻り値は、ソースを参照して下さい。)
関数名 関数の機能 呼び出し例 計算法
cbrt( ) 立方根 y = cbrt(x); Newton-Raphson 法
besj0( ) ベッセル関数 第1種 J0(x) y = besj0(x); Hickcock の近似式
besj1( ) 第1種 J1(x) y = besj1(x);
besy0( ) 第2種 Y0(x) y = besy0(x); Allen の近似式
besy1( ) 第2種 Y1(x) y = besy1(x);
besi0( ) 第1種変形 I0(x) y = besi0(x); Allen の近似式
besi1( ) 第1種変形 I1(x) y = besi1(x);
besk0( ) 第2種変形 K0(x) y = besk0(x); Allen の近似式
besk1( ) 第2種変形 K1(x) y = besk1(x);
erfnc( ) 誤差関数 y = erfnc(x); Hastings の近似式
gammaf( ) ガンマ関数Γ(x) y = gammaf(x); Hastings の近似式
legend( ) ルジャンドルの多項式 y = legend(x, n); 漸化式
celi1( ) 完全楕円積分 第1種 y = celi1(x, eps); 算術幾何平均法
celi2( ) 第2種 y = celi2(x, eps);

プログラム・ソース("function.c")           top (トップに戻る)
/*		function.c		*/
#include <stdio.h>
#include "sslib.h"

double cbrt(double a)
{
	double	w;

	if(a == 0.)	return 0.;
	w = pow(fabs(a), 1./ 3.);
	if(a < 0.)	w = -w;
	return (w + 3. * a / (2. * w * w + a / w)) / 2.;
}

double besj0(double x)
{
	int i;
	double w, wp, wq, wx4;
	static double a[7] = {	 1.0,          -3.9999998721, 3.9999973021,
							-1.7777560599, 0.4443584263, -0.0709253492,
							 0.0076771853};
	static double c[5] = {	 0.3989422793, -0.00175302,   0.00017343,
							-0.0000487613,  0.0000173565};
	static double k[5] = {	-0.0124669441,  0.0004564324, -0.0000869791,
							 0.0000342468, -0.0000142078};

	if(x < 0.)
	{
		fprintf(stderr, "Error : x < 0 in besj0()\n");
		return 0.;
	}
	wx4 = x * x / 16.;
	if(x <= 4.)
	{
		w = -0.0005014415;
		for(i = 6; i >= 0; i--)	w = w * wx4 + a[i];
		return w;
	}
	wx4 = 1. / wx4;
	wp = -0.0000037043;
	wq =  0.0000032312;
	for(i = 4; i >= 0; i--)
	{
		wp = wp * wx4 + c[i];
		wq = wq * wx4 + k[i];
	}
	w = x - 0.78539816339744831;
	wp *= cos(w);
	wq *= sin(w);
	return 2. / sqrt(x) * (wp - 4. * wq / x);
}

double besj1(double x)
{
	int i;
	double w, wp, wq, wx4;
	static double a[7] = {	 1.9999999998, -3.999999971,   2.6666660544,
							-0.8888839649,  0.1777582922, -0.0236616773,
							 0.0022069155};
	static double c[5] = {	 0.3989422819,  0.0029218256, -0.000223203,
							 0.0000580759, -0.000020092};
	static double k[5] = {	 0.0374008364, -0.00063904,    0.0001064741,
							-0.0000398708,  0.00001622};

	if(x < 0.)
	{
		fprintf(stderr, "Error : x < 0 in besj1()\n");
		return 0.;
	}
	wx4 = x * x / 16.;
	if(x <= 4.)
	{
		w = -0.0001289769;
		for(i = 6; i >= 0; i--)	w = w * wx4 + a[i];
		return w * x / 4.;
	}
	wx4 = 1. / wx4;
	wp =  0.0000042414;
	wq = -0.0000036594;
	for(i = 4; i >= 0; i--)
	{
		wp = wp * wx4 + c[i];
		wq = wq * wx4 + k[i];
	}
	w = x - 2.356194490192345;
	wp *= cos(w);
	wq *= sin(w);
	return 2. / sqrt(x) * (wp - 4. * wq / x);
}

double besy0(double x)
{
	int i;
	double bj0, w, wf, wp, wx3;
	static double a[6] = {	 0.36746691,  0.60559366, -0.74350384,
							 0.25300117, -0.04261214,  0.00427916};
	static double b[6] = {	 1.0,        -2.2499997,   1.2656208,
							-0.3163866,   0.0444479,  -0.0039444};
	static double c[6] = {	 0.79788456, -0.00000077, -0.0055274,
							-0.00009512,  0.00137237, -0.00072805};
	static double k[6] = {	 0.78539816,  0.04166397,  0.00003954,
							-0.00262573,  0.00054125,  0.00029333};

	if(x <= 0.)
	{
		fprintf(stderr, "Error : x <= 0  in besy0()\n");
		return 0.;
	}
	if(x <= 3.)
	{
		w = -0.00024846;
		bj0 = 0.00021;
		wx3 = x * x / 9.;
		for(i = 5; i >= 0; i--)
		{
			w = w * wx3 + a[i];
			bj0 = bj0 * wx3 + b[i];
		}
		return w + 0.636619772367581 * log(x / 2.) * bj0;
	}
	wx3 = 3. / x;
	wf = 0.00014476;
	wp = -0.00013558;
	for(i = 5; i >= 0; i--)
	{
		wf = wf * wx3 + c[i];
		wp = wp * wx3 + k[i];
	}
	return wf * sin(x - wp) / sqrt(x);
}

double besy1(double x)
{
	int i;
	double bj1, w, wf, wp, wx3;
	static double a[6] = {	-0.6366198,  0.2212091,  2.1682709,
							-1.3164827,  0.3123951, -0.0400976};
	static double b[6] = {	 0.5,        -0.56249985,  0.21093573,
							-0.03954289,  0.00443319, -0.00031761};
	static double c[6] = {	 0.79788456,  0.00000156,  0.01659667,
							 0.00017105, -0.00249511,  0.00113653};
	static double k[6] = {	 0.78539816, -0.12499612, -0.0000565,
							 0.00637879, -0.00074348, -0.00079824};

	if(x <= 0.)
	{
		fprintf(stderr, "Error : x <= 0  in besy1()\n");
		return 0.;
	}
	if(x <= 3.)
	{
		w = 0.0027873;
		bj1 = 0.00001109;
		wx3 = x * x / 9.;
		for(i = 5; i >= 0; i--)
		{
			w = w * wx3 + a[i];
			bj1 = bj1 * wx3 + b[i];
		}
		return w / x + M_2_PI * log(x / 2.) * bj1 * x;
	}
	wx3 = 3. / x;
	wf = -0.00020033;
	wp = 0.00029166;
	for(i = 5; i >= 0; i--)
	{
		wf = wf * wx3 + c[i];
		wp = wp * wx3 + k[i];
	}
	return - wf * cos(x - wp) / sqrt(x);
}

double besi0(double x)
{
	int i;
	double w, wx375;
	static double a[6] = {	 1.0,        3.5156229,  3.0899424,
							 1.2067492,  0.2659732,  0.0360768};
	static double b[8] = {	 0.39894228,   0.013285917,  0.002253187,
							-0.001575649,  0.009162808, -0.020577063,
							 0.026355372, -0.016476329};

	if(x < 0.)
	{
		fprintf(stderr, "Error : x < 0  in besi0()\n");
		return 0.;
	}
	if(x <= 3.75)
	{
		wx375 = x * x / 14.0625;
		w = 0.0045813;
		for(i = 5; i >= 0; i--)	w = w * wx375 + a[i];
		return w;
	}
	wx375 = 3.75 / x;
	w = 0.003923767;
	for(i = 7; i >= 0; i--)	w = w * wx375 + b[i];
	return w / sqrt(x) * exp(x);
}

double besi1(double x)
{
	int i;
	double w, wx375;
	static double a[6] = {	 0.5,        0.87890594,  0.51498869,
							 0.15084934, 0.02658733,  0.00301532};
	static double b[8] = {	 0.39894228,  -0.039880242, -0.003620183,
							 0.001638014, -0.01031555,   0.022829673,
							-0.028953121,  0.017876535};

	if(x < 0.)
	{
		fprintf(stderr, "Error : x < 0  in besi1()\n");
		return 0.;
	}
	if(x <= 3.75)
	{
		wx375 = x * x / 14.0625;
		w = 0.00032411;
		for(i = 5; i >= 0; i--)	w = w * wx375 + a[i];
		return w * x;
	}
	wx375 = 3.75 / x;
	w = -0.004200587;
	for(i = 7; i >= 0; i--)	w = w * wx375 + b[i];
	return w / sqrt(x) * exp(x);
}

double besk0(double x)
{
	int i;
	double bi0, w, wx2, wx375;
	static double a[6] = {	-0.57721566,  0.42278442,  0.23069756,
							 0.0348859,   0.00262698,  0.0001075};
	static double b[6] = {	 1.0,        3.5156229,  3.0899424,
							 1.2067492,  0.2659732,  0.0360768};
	static double c[6] = {	 1.25331414, -0.07832358,  0.02189568,
							-0.01062446,  0.00587872, -0.0025154};

	if(x <= 0.)
	{
		fprintf(stderr, "Error : x <= 0  in besk0()\n");
		return 0.;
	}
	if(x <= 2.)
	{
		wx2 = x * x / 4.;
		wx375 = x * x / 14.0625;
		w = 0.0000074;
		bi0 = 0.0045813;
		for(i = 5; i >= 0; i--)
		{
			w = w * wx2 + a[i];
			bi0 = bi0 * wx375 + b[i];
		}
		return w - log(x / 2.) * bi0;
	}
	wx2 = 2. / x;
	w = 0.00053208;
	for(i = 5; i >= 0; i--)	w = w * wx2 + c[i];
	return w / sqrt(x) / exp(x);
}

double besk1(double x)
{
	int i;
	double bi1, w, wx2, wx375;
	static double a[6] = {	 1.0,         0.15443144, -0.67278579,
							-0.18156897, -0.01919402, -0.00110404};
	static double b[6] = {	 0.5,         0.87890594,  0.51498869,
							 0.15084934,  0.02658733,  0.003011532};
	static double c[6] = {	 1.25331414,  0.23498619, -0.0365562,
							 0.01504268, -0.00780353,  0.00325614};

	if(x <= 0.)
	{
		fprintf(stderr, "Error : x <= 0  in besk1()\n");
		return 0.;
	}
	if(x <= 2.)
	{
		wx2 = x * x / 4.;
		wx375 = x * x / 14.0625;
		w = -0.00004686;
		bi1 = 0.00032411;
		for(i = 5; i >= 0; i--)
		{
			w = w * wx2 + a[i];
			bi1 = bi1 * wx375 + b[i];
		}
		return w / x + log(x / 2.) * bi1 * x;
	}
	wx2 = 2. / x;
	w = -0.00068245;
	for(i = 5; i >= 0; i--)	w = w * wx2 + c[i];
	return w / sqrt(x) / exp(x);
}

double erfnc(double x)
{
	int i;
	double w;
	static double a[6] = {	 1.0,           0.0705230784,  0.0422820123,
							 0.0092705272,	0.0001520143,  0.0002765672};

	if(x < 0.)
	{
		fprintf(stderr, "Error : x < 0  in erfnc()\n");
		return 0.;
	}
	if(x == 0.)	return 0.;
	if(x >= 10.)	return 1.;
	w = 0.0000430638;
	for(i = 5; i >= 0; i--)	w = w * x + a[i];
	for(i = 0; i < 4; i++)	w *= w;
	return 1. - 1. / w;
}

double gammaf(double x)
{
	int i;
	double w, w1;
	static double a[8] = {	 1.0,         -0.577191652,  0.988205891,
							-0.897056937,  0.918206857, -0.756704078,
							 0.482199394, -0.193527818};

	if(x <= 0.)
	{
		fprintf(stderr, "Error : x <= 0  in gammaf()\n");
		return 0.;
	}
	if(x >= 34.)
	{
		fprintf(stderr,	"Error : x >= 34  (Overflow) in gammaf()\n");
		return 0.;
	}
	w1 = 1.;
	if(x > 1.)
	{
		do
		{
			x -= 1.;
			w1 *= x;
		} while(x > 1.);
	}
	w = 0.035868343;
	for(i = 7; i >= 0; i--)	w = w * x + a[i];
	return w1 * w / x;
}

double legend(double x, int n)
{
	double p0, p1, p2, w, wn;

	if(n < 0)
	{
		fprintf(stderr, "Error : n < 0  in legend()\n");
		return 0.;
	}
	if(n == 0)	return 1.;
	if(n == 1)	return x;
	wn = (double)n;
	p0 = 1.;
	p1 = x;
	do
	{
		wn -= 1.;
		w = wn / (wn + 1.);
		p2 = x * p1 + w * (x * p1 - p0);
		p0 = p1;
		p1 = p2;
	} while(wn >= 2.);
	return p2;
}

double celi1(double k, double eps)
{
	double a0, a1, b0, b1;

	if(eps <= 0.)
	{
		fprintf(stderr, "Error : Illegal parameter  in celi1()\n");
		return 0.;
	}
	if(fabs(k) > 1.)
	{
		fprintf(stderr, "Error : |k| > 1  in celi1()\n");
		return 0.;
	}
	a0 = 1.;
	b0 = sqrt(1. - k * k);
	for(;;)
	{
		a1 = (a0 + b0) / 2.;
		b1 = sqrt(a0 * b0);
		if(fabs(a1 - b1) <= eps)	return M_PI_2 / a1;
		a0 = a1;
		b0 = b1;
	}
}

double celi2(double k, double eps)
{
	int i, j;
	double a0, a1, b0, b1, c0, c1, cn, w;

	if(eps <= 0.)
	{
		fprintf(stderr, "Error : Illegal parameter  in celi2()\n");
		return 0.;
	}
	if(fabs(k) > 1.)
	{
		fprintf(stderr, "Error : |k| > 1  in celi2()\n");
		return 0.;
	}
	a0 = 1.;
	c0 = k * k;
	b0 = sqrt(1. - c0);
	cn = 0.;
	i = 0;
	for(;;)
	{
		a1 = (a0 + b0) / 2.;
		b1 = sqrt(a0 * b0);
		c1 = (a0 - b0) / 2.;
		w = 1.;
		for(j = 0; j < i; j++)	w *= 2.;
		cn += w * c1 * c1;
		i++;
		if(fabs(a1 - b1) < eps)	return M_PI_2 / a1 * (1. - (c0 / 2. + cn));
		a0 = a1;
		b0 = b1;
	}
}