home *** CD-ROM | disk | FTP | other *** search
- { unit SpecFun/SpecF87 }
- { Special functions for mathematical calculations }
- { Copyright 1990, by J. W. Rider. }
-
- unit {$IFOPT N-} SpecFun {$ELSE} SpecF87 {$ENDIF} ;
-
- interface
-
- uses {$IFOPT N-} Math {$ELSE} Math87 {$ENDIF} ;
-
- function factorial (n:word):xfloat;
- function lnfactorial(n:word):xfloat;
-
- function permutation(n,k:word):xfloat;
- function combination(n,k:word):xfloat;
-
- function gamma (x:xfloat):xfloat;
- function lngamma(x:xfloat):xfloat;
-
- function beta (x,y:xfloat):xfloat;
- function lnbeta(x,y:xfloat):xfloat;
-
- function igamma (a,x:xfloat):xfloat;
- function igammac(a,x:xfloat):xfloat;
- function igammap(a,x:xfloat):xfloat;
- function igammaq(a,x:xfloat):xfloat;
-
- function ibeta (a,b,x:xfloat):xfloat;
- function ibetap(a,b,x:xfloat):xfloat;
- function ibetaq(a,b,x:xfloat):xfloat;
-
- function erf (x:xfloat):xfloat;
- function erfc(x:xfloat):xfloat;
-
-
- implementation
-
- { IBETACF is a "continued fraction" evaluation of an incomplete
- beta auxiliary function. (See HMF: eqn. 26.5.8; NR: BETACF ) }
-
- function ibetacf(a,b,x:xfloat):xfloat;
- var am,ap,apb,app,azlast,az,bm,bp,bpp,bz,d,deca,inca:xfloat;
- m,tm:longint;
- begin
- am:=1; az:=1; bm:=1; m:=1; apb:=a+b; deca:=a-1; inca:=a+1;
- bz:=1-apb*x/inca; tm:=2; d:=(b-1)*x/(inca*(a+2));
- ap:=d+1; bp:=bz+d; d:=-inca*(apb+1)*x/((a+2)*(a+3));
- app:=ap+d; bpp:=bp+d*bz; am:=ap/bpp; bm:=bp/bpp;
- azlast:=az; az:=app/bpp;
- while abs(az-azlast)>(abs(az)*FLOATEPS) do begin
- inc(m); inc(tm,2); d:=m*(b-m)*x/((deca+tm)*(a+tm));
- ap:=az+d*am; bp:=d*bm+1; d:=-(a+m)*(apb+m)*x/((a+tm)*(inca+tm));
- app:=ap+d*az; bpp:=bp+d end;
- ibetacf:=az end; { ibetacf }
-
-
- { IGAMMACF is a "continued fraction" evaluation of an incomplete
- gamma auxiliary function. ( See HMF: eqn. 6.5.31; NR: GCF ) }
-
- function igammacf(a,x:xfloat):xfloat;
- var n:longint; a0,a1,b0,b1,f,fn,g,glast,na:xfloat;
- begin
- a0:=1; a1:=x; b0:=0; b1:=1; f:=1; g:=0; glast:=1; n:=0;
- repeat
- inc(n); fn:=f*n; na:=n-a;
- a0:=(a1+a0*na)*f; b0:=(b1+b0*na)*f;
- a1:=x*a0+fn*a1; b1:=x*b0+fn*b1;
- if (a1<>0) then begin f:=1/a1; glast:=g; g:=b1*f end;
- until abs(g-glast)<(abs(g)*FLOATEPS);
- igammacf:=g; end; { igammacf }
-
-
- { IGAMMASER is a "power series" evaluation of the incomplete
- gamma auxiliary function. ( See HMF: eqn. 6.5.29; NR: GSER ) }
-
- function igammaser(a,x:xfloat):xfloat; var d,s:xfloat;
- begin if x=0 then igammaser:=0
- else begin
- d:=1/a; s:=d;
- repeat
- a:=a+1; d:=d*x/a; s:=s+d;
- until abs(d)<(abs(s)*FLOATEPS);
- igammaser:=s end end; { igammaser }
-
-
- { *** interface'd functions in alphabetical order *** }
-
- function beta; begin beta:=exp(lnbeta(x,y)) end;
-
- function combination; begin
- combination:=round(exp(lnfactorial(n)
- -lnfactorial(k)-lnfactorial(n-k))) end;
-
- function erf; var y,z:xfloat;
- begin if abs(x)<FLOATEPS then erf:=x*R2_SQRTPI
- else if abs(x)>10 then erf:=sgn(x)
- else begin
- y:=sqr(x); z:=x*exp(-y-SQRTPI);
- if y<1.5 then erf:=z*igammaser(0.5,y)
- else erf:=sgn(x)-z*igammacf(0.5,y) end end; { erf }
-
- function erfc; begin erfc:=1-erf(x) end;
-
- function factorial;
- const MAXATYPE = 32;
- type atype = array[0..MAXATYPE] of xfloat;
- const a : ^atype = NIL; atop:shortint = -1;
- var j:byte;
- begin
- if a=NIL then begin
- new(a); if a<>NIL then begin a^[0]:=1; atop:=0 end end;
- if (a<>NIL) and (n>atop) and (n<=MAXATYPE) then begin
- for j:=succ(atop) to n do a^[j]:=a^[pred(j)]*j;
- atop:=n end;
- if (n<=atop) then factorial:=a^[n]
- else factorial:=round(gamma(succ(n))) end; { factorial }
-
- function gamma; var y:xfloat; begin
- y:=exp(lngamma(x));
- if x<0 then if not odd(trunc(x)) then y:=-y;
- gamma:=y end;
-
- function ibeta; var y:xfloat; begin
- if x<=0 then ibeta:=0
- else if x>=1 then ibeta:=beta(a,b)
- else begin
- y:=exp(a*ln(x)+b*ln(1-x));
- if (x*(a+b+2))<=(a+1) then ibeta:=y*ibetacf(a,b,x)/a
- else ibeta:=beta(a,b)-y*ibetacf(b,a,1-x)/b end end; { ibeta }
-
- function ibetap; var y:xfloat; begin
- if x<=0 then ibetap:=0
- else if x>=1 then ibetap:=1
- else begin
- y:=exp(-lnbeta(a,b)+a*ln(x)+b*ln(1-x));
- if x<=(a+1)/(a+b+2) then ibetap:=y*ibetacf(a,b,x)/a
- else ibetap:=1-y*ibetacf(b,a,1-x)/b end end; { ibetap }
-
- function ibetaq; begin ibetaq:=1-ibetap(b,a,1-x) end;
-
- function igamma; begin
- if x<=0 then igamma:=0
- else if x<(a+1) then igamma:=exp(-x+a*ln(x))*igammaser(a,x)
- else igamma:=gamma(a)-igammac(a,x) end;
-
- function igammac; begin
- if x<(a+1) then igammac:=gamma(a)-igamma(a,x)
- else igammac:=exp(-x+a*ln(x))*igammacf(a,x) end;
-
- function igammap; begin
- if x<=0 then igammap:=0
- else if x<(a+1) then igammap:=exp(-x+a*ln(x)-lngamma(a))
- *igammaser(a,x)
- else igammap:=1-igammaq(a,x) end;
-
- function igammaq; begin
- if x<(a+1) then igammaq:=1-igammap(a,x)
- else igammaq:=exp(-x+a*ln(x)-lngamma(a))
- *igammacf(a,x) end;
-
- function lnbeta; begin lnbeta:=lngamma(x)+lngamma(y)-lngamma(x+y) end;
-
- function lnfactorial;
- const MAXATYPE = 99;
- type atype = array[0..MAXATYPE] of xfloat;
- const a:^atype = NIL;
- var j:byte;
- begin
- if a=NIL then begin
- new(a);
- if a<>NIL then for j:=0 to MAXATYPE do a^[j]:=-1 end;
- if (n<MAXATYPE) and (a<>NIL) then begin
- if a^[n]<0 then a^[n]:=lngamma(succ(n));
- lnfactorial:=a^[n] end
- else lnfactorial:=lngamma(succ(n)) end; { lnfactorial }
-
- function lngamma; var s,t:xfloat; begin
- if x<0 then lngamma:=LNPI-lngamma(1-x)-ln(sin(frac(x*0.5)*TWOPI))
- else if x<1 then lngamma:=lngamma(x+1)-ln(x)
- else begin
- t:=x+4.5; t:=(x-0.5)*ln(t)-t;
- s:=1 + 76.18009173/x - 86.50532033 /(x+1) + 24.01409822/(x+2)
- - 1.231739516/(x+3) + 1.20858003e-3/(x+4) - 5.3682E-6 /(x+5);
- lngamma:=t+ln(SQRT2PI*s) end end; { lngamma }
-
- function permutation; begin
- permutation:=round(exp(lnfactorial(n)-lnfactorial(n-k))) end;
-
- end. { unit specfun/specf87 }
-