📄 specfunc.pas
字号:
{
@abstract(EBK&NVS Pascal-Delphi Math Library: Real Special functions)
@author(Nikolai V. Shokhirev <nikolai@shokhirev.com> <nikolai@u.arizona.edu>)
@author(Eugene B. Krissinel <keb@ebi.ac.uk> <krissinel@fh.huji.ac.il>)
@created(09.09.1991)
@lastmod(04.04.2002)
This is a temporary publication (reduced variant), will be updated later
check: http://www.shokhirev.com/nikolai/programs/samplecode.html
㎞ikolai V. Shokhirev, 2002
}
unit SpecFunc;
interface
uses
MathTypes;
const
ln10 = 2.3025850929940456840179915;
Gamma_Eu = 0.577215664901532860606512;
{ Basic functions for the Real Calculations }
function iSign(x: IntType) : IntType;
function Sign(x: RealType) : RealType;
function Sign2(a, b: RealType) : RealType;
function Combinations(m, n: IntType): IntType;
function Fac(m: IntType) : IntType;
function power10(x: RealType) : RealType;
function lg(x: RealType) : RealType;
function amin2(x1, x2: RealType): RealType;
function amax2(x1, x2: RealType): RealType;
function sqroot1(x, y: RealType): RealType; { safe sqrt(x + y) }
function sqroot2(x, y: RealType): RealType; { safe sqrt(x*x+y*y) }
{ Hyperbolic Functions }
function ArcSin(x: RealType): RealType;
function ArcCos(X: RealType): RealType;
function exp1(X: RealType) : RealType;
function ch(x: RealType) : RealType;
function sh(x: RealType) : RealType;
function th (x: RealType): RealType;
function arch (x: RealType): RealType;
function arsh (x: RealType): RealType;
function arth (x: RealType): RealType;
{ Special functions for the Real Calculations }
function er(x: Realtype) : RealType; { er(x) = exp(x**2)*erfc(x) }
function erf(x: Realtype) : RealType; { error function: 1 = erfc+erf }
function erfc(x: Realtype) : RealType; { complementary error function }
function I0_(x: RealType) : RealType; { Modified Bessel function }
function I1_(x: RealType) : RealType; { Modified Bessel function }
function K0_(x: RealType) : RealType; { Modified Bessel function }
function K1_(x: RealType) : RealType; { Modified Bessel function }
function fk0_(x: RealType) : RealType; { fk0(x)=K0(x)+ln(x/2)*I0(x) }
function fk1_(x: RealType) : RealType; { fk1(x)=K1(x)-ln(x/2)*I1(x) }
function gamma_(x: Realtype) : RealType; { gamma-function }
function gamma_in(a,x: Realtype): RealType; { incomplete gamma-function }
function E1_(x: Realtype) : RealType; { integral exp-function }
function I_nu(nu, x: RealType) : RealType; { Modified Bessel function }
(*)
{ Undocumented Functions }
function Gamma(x: RealType): RealType;
function PolyGamma(n: IntType; z: RealType): RealType;
function GammaX(a,x: RealType): RealType;
function BJn (n,x: RealType): RealType;
function BIn (n,x: RealType): RealType;
function BKn (n,x: RealType): RealType;
function Sn(n: IntType; z: RealType): RealType;
function Un(n: IntType; z,a: RealType): RealType;
(*)
{ =================================================================== }
implementation
{ Basic functions for the Real Calculations }
function iSign (x: IntType): IntType;
begin
if x > 0 then result := 1 else
if x = 0 then result := 0 else
result := -1;
end;
function sign(x: RealType): RealType;
begin
if x > 0.0 then sign := 1.0
else if x < 0.0 then sign := -1.0
else sign := 0.0;
end;
function Sign2(a, b: RealType): RealType;
begin
if b < 0.0 then result := - abs(a)
else result := abs(a) ;
end;
function Combinations(m, n: IntType): IntType;
var
i, C : IntType;
begin
C := 1;
if m > 0 then
for i := 1 to m do
C := (C*(n-i+1)) div i;
Combinations := C;
end;
function Fac(m: IntType): IntType;
var
i, z: IntType;
begin
z := 1;
if m > 1 then
for i := 2 to m do
z := z*i;
Fac := z;
end;
function power10(x: RealType): RealType;
begin
if x > -MaxExp then power10 := exp1(x*ln(10.0))
else power10 := 1.0;
end;
function lg(x: RealType): RealType;
begin
lg := ln(x)/ln(10.0);
end;
function amin2(x1,x2: RealType): RealType;
begin
if x1 < x2 then amin2 := x1
else amin2 := x2;
end;
function amax2(x1,x2: RealType): RealType;
begin
if x1 > x2 then amax2 := x1
else amax2 := x2;
end;
function ArcSin (x: RealType): RealType;
var
R,S,y : RealType;
l : IntType;
begin
if x>=1.0 then ArcSin := Pi/2.0
else if x<=-1.0 then ArcSin := -Pi/2.0
else
begin
if abs(x)<0.71 then y := x
else y := sqrt(1.0-sqr(x));
S := 0.0;
R := y;
l := 1;
repeat
S := S+R;
R := R*sqr(y*l)/((l+1) * (l+2));
l := l+2;
until (abs(R)<1.0e-35) or
(abs(R)<=1.0e-16*abs(S));
S := S+R;
if abs(x-y)>1.0e-12 then
begin
if x>0.0 then S := Pi/2.0-S
else S := -Pi/2.0+S;
end;
ArcSin := S;
end;
end;
function ArcCos(X: RealType): RealType;
begin
ArcCos := Pi*0.5 - ArcSin(X);
end;
function exp1(X: RealType): RealType;{ exp with underflow protection}
begin
if X = 0.0 then exp1 := 1.0
else if X > -ExpArg then exp1 := exp(X)
else exp1 := 0.0;
end;
function sqroot1(x, y: RealType) : RealType;
{ safe sqrt: sqroot = sqrt(x + y) }
begin
if x > y then
result := sqrt(x)*sqrt(1.0 + y/x)
else
result := sqrt(y)*sqrt(1.0 + x/y);
end;
function sqroot2(x, y: RealType) : RealType;
{ safe sqrt: sqroot = sqrt(x*x+y*y) }
begin
if abs(x) > abs(y) then
result := abs(x)*sqrt(1.0+sqr(y/x))
else
result := abs(y)*sqrt(1.0+sqr(x/y));
end;
{ Hyperbolic Functions }
function ch(x: RealType): RealType;
begin
ch := 0.5*(exp1(x)+exp1(-x));
end;
function sh(x: RealType): RealType;
begin
sh := 0.5*(exp1(x)-exp1(-x));
end;
function th(x: RealType): RealType;
begin
th := (1.0-exp1(-2.0*x))/(1.0+exp1(-2.0*x));
end;
function arch(x: RealType): RealType;
begin
arch := ln(x + sqrt(sqr(x)-1.0) );
end;
function arsh(x: RealType): RealType;
begin
arsh := ln(x + sqrt(sqr(x)+1.0) );
end;
function arth(x: RealType): RealType;
begin
arth := 0.5 * ln((1.0+x)/(1.0-x));
end;
{ Special functions for the Real Calculations }
function er(x: Realtype): RealType;
const
epsilon = 1.0E-14;
sp = 1.7724538509055160;{ sqrt(pi) }
a1 = 0.4613135; b1 = 0.1901635;
a2 = 0.09999216; b2 = 1.7844927;
a3 = 0.002883894; b3 = 5.5253437;
var
s, t, m, xx, xx2 : RealType;
begin
xx := x*x;
if abs(x) < 3.0
then { series expansion of er(x) }
begin
m := 1.0; t := 1.0;
s := 0.0; xx2 := xx*2.0;
repeat
s := s + t; m := m + 2.0;
t := t*xx2; t := t/m;
until (abs(t) < epsilon);
er := exp1(xx) - s*x*2.0/sp;
end
else{ asymptotics from Abramowitz }
if x > 0.0 then
er := x*(a1/(b1+xx)+a2/(b2+xx)+a3/(b3+xx))
else
er := exp1(xx)*2.0 +
x*(a1/(b1+xx)+a2/(b2+xx)+a3/(b3+xx));
end;{ of er }
function erf(x: Realtype): RealType;
const
epsilon = 1.0E-14;
sp = 1.7724538509055160;{ sqrt(pi) }
a1 = 0.4613135; b1 = 0.1901635;
a2 = 0.09999216; b2 = 1.7844927;
a3 = 0.002883894; b3 = 5.5253437;
var
s, t, m, xx, xx2 : RealType;
begin
xx := x*x;
if abs(x) < 3.0
then { series expansion of erf(x) }
begin
m := 1.0; t := 1.0;
s := 0.0; xx2 := xx*2.0;
repeat
s := s + t; m := m + 2.0; t := t*xx2/m;
until (abs(t)<epsilon);
erf := exp1(-xx)*s*x*2.0/sp;
end
else{ asimptotics from Abramowitz }
erf := sign(x) - exp1(-xx)*x*(a1/(b1+xx)+a2/(b2+xx)+a3/(b3+xx));
end;
function erfc(x: Realtype): RealType;
begin
erfc := 1.0 - erf(x);
end;
function I0_(x: RealType): RealType;
var
r : RealType;
begin
if x < 3.75 then
begin
r := sqr(x/3.75);
I0_:= 1.0+r*(3.5156229+r*(3.0899424+r*(1.2067492
+r*(0.2659732+r*(0.0360768+r*0.0045813)))));
end else
begin
r := 3.75/x;
I0_:=exp1(x)*(0.39894228+r*(0.01328592+r*(0.00225319
+r*(-0.00157565+r*(0.00916281+r*(-0.02057706
+r*(0.02635537+r*(-0.01647633+r*0.00392377))))))))/sqrt(x);
end;
end;
function I1_(x: RealType): RealType;
var
r : RealType;
begin
if x < 3.75 then
begin
r := sqr(x/3.75);
I1_:= (0.5+r*(0.87890594+r*(0.51498869+r*(0.15084934
+r*(0.02658733+r*(0.00301532+r*0.00032411))))))*x;
end else
begin
r := 3.75/x;
I1_:=exp1(x)*(0.39894228+r*(-0.03988024+r*(-0.00362018
+r*(0.00163801+r*(-0.01031555+r*(0.02282967
+r*(-0.02895312+r*(0.01787654-r*0.00420059))))))))/sqrt(x);
end;
end;
function fk0_(x: RealType): RealType;
var
r : RealType;
begin
r := sqr(x/2.0);
fk0_:= -0.57721566+r*(0.42278420+r*(0.23069756+r*(0.03488590
+r*(0.00262698+r*(0.0001075+r*0.0000074)))));
end;
function K0_(x: RealType): RealType;
var
r : RealType;
begin
if x < 2.0
then
K0_:= -ln(x/2.0)*I0_(x) + fk0_(x)
else
begin
r := 2.0/x;
K0_:=exp1(-x)*(1.25331414+r*(-0.07832358
+r*(0.02189568+r*(-0.01062446+r*(0.00587872
+r*(-0.00251540+r*0.00053208))))))/sqrt(x);
end;
end;
function fk1_(x: RealType): RealType;
var
r: RealType;
begin
r := sqr(x/2.0);
fk1_:= (1.0+r*(0.15443144-r*(0.67278579+r*(0.18156897
+r*(0.01919402+r*(0.00110404+r*0.00004686))))))/x;
end;
function K1_(x: RealType): RealType;
var
r: RealType;
begin
if x < 2.0
then
K1_:= ln(x/2.0)*I1_(x)+fk1_(x)
else
begin
r := 2.0/x;
K1_:=exp1(-x)*(1.25331414+r*(0.23498619
+r*(-0.03655620+r*(0.01504268+r*(-0.00780353
+r*(0.00325614-r*0.00068245))))))/sqrt(x)
end;
end;
function gamma_(x: Realtype) : RealType;
{ gamma-function error < 1 e-6 }
const{ for expansion from Abramowitz }
b1 = -0.577191652; b2 = 0.988205891;
b3 = -0.897056937; b4 = 0.918206857;
b5 = -0.756704078; b6 = 0.482199394;
b7 = -0.193527818; b8 = 0.035868343;
var
t : RealType;
begin
t := 1.0;
while x >= 2.0 do begin x := x - 1.0; t := t*x; end;
while x < 1.0 do begin t := t/x; x := x + 1.0; end;
x := x - 1.0;
gamma_:=t*((((((((b8*x+b7)*x+b6)*x+b5)*x+b4)*x+b3)*x+b2)*x+b1)*x+1.0);
end;
function gamma_in(a, x :Realtype): RealType;
const
epsilon = 1.0E-8;
Xmax = 10.0;
var
s, t, m: RealType;
begin
if x < Xmax then { series expansion }
begin
m := 0.0; t := exp1(a*ln(x))/a; s := t;
repeat
m := m + 1.0; t := -t*x*a/(a+1.0)/m;
s := s + t; a := a + 1.0;
until (abs(t)<epsilon);
gamma_in := s;
end
else{ asimptotics from Abramowitz }
begin
m := a - 1.0; t := exp1(m*ln(x)-x); s := t;
repeat
t := t*m/x; s := s + t; m := m - 1.0;
until (abs(t)<epsilon) or (abs(a) > x);
gamma_in := gamma_(a) - s;
end;
end;
function E1_(x: Realtype) : RealType;
const
epsilon = 1.0E-9;
Xmax = 10.0;
gamma = 0.57721566490153286;{ Euler's constant }
var
s, t, m : RealType;
begin
if x < Xmax then { series expansion }
begin
m := 1.0; t := x; s := t - gamma - ln(x);
repeat
t := -t*x*m/sqr(m+1.0);
s := s + t; m := m + 1.0;
until (abs(t)<epsilon);
E1_ := s;
end
else{ asymptotics from Abramowitz }
begin
m := 1.0; t := exp1(-x)/x; s := t;
repeat
t := -t*m/x; s := s + t; m := m + 1.0;
until (abs(t)<epsilon) or (m > x);
E1_ := s;
end;
end;
function I_nu(nu, x: RealType): RealType;
const
epsilon = 1.0E-7;
Xmax = 10.0;
s2pi = 2.506628274631;{ sqrt(2*pi) }
var
s, t, m, f, n, x8: RealType;
begin
if x < Xmax then { series expansion }
begin
x := x/2.0; t := exp1(nu*ln(x)); x := sqr(x);
nu := nu + 1.0; t := t/gamma_(nu); m := 1.0;
s := t;
repeat
t := t*x/m/nu; s := s + t;
nu := nu +1.0; m := m + 1.0;
until (abs(t)<epsilon);
I_nu := s;
end
else{ asimptotics from Abramowitz }
begin
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -