home *** CD-ROM | disk | FTP | other *** search
- (*-------------------------------------------------------------------------*)
- (* ALGama -- Logarithm of Gamma Distribution *)
- (*-------------------------------------------------------------------------*)
-
- FUNCTION ALGama( Arg : REAL ) : REAL;
-
- (*-------------------------------------------------------------------------*)
- (* *)
- (* Function: ALGama *)
- (* *)
- (* Purpose: Calculates Log (base E) of Gamma function *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Val := ALGama( Arg ) *)
- (* *)
- (* Arg --- Gamma distribution parameter (Input) *)
- (* Val --- output Log Gamma value *)
- (* *)
- (* Calls: None *)
- (* *)
- (* Called By: Many (CDBeta, etc.) *)
- (* *)
- (* Remarks: *)
- (* *)
- (* Minimax polynomial approximations are used over the *)
- (* intervals [-inf,0], [0,.5], [.5,1.5], [1.5,4.0], *)
- (* [4.0,12.0], [12.0,+inf]. *)
- (* *)
- (* See Hart et al, "Computer Approximations", *)
- (* Wiley(1968), p. 130F, and also *)
- (* *)
- (* Cody and Hillstrom, "Chebyshev approximations for *)
- (* the natural logarithm of the Gamma function", *)
- (* Mathematics of Computation, 21, April, 1967, P. 198F. *)
- (* *)
- (* *)
- (* There are some machine-dependent constants used -- *)
- (* *)
- (* Rmax --- Largest value for which ALGama *)
- (* can be safely computed. *)
- (* Rinf --- Largest floating-point number. *)
- (* Zeta --- Smallest floating-point number *)
- (* such that (1 + Zeta) = 1. *)
- (* *)
- (*-------------------------------------------------------------------------*)
-
- VAR
- Rarg : REAL;
- Alinc : REAL;
- Scale : REAL;
- Top : REAL;
- Bot : REAL;
- Frac : REAL;
- Algval : REAL;
-
- I : INTEGER;
- Iapprox : INTEGER;
- Iof : INTEGER;
- Ilo : INTEGER;
- Ihi : INTEGER;
-
- Qminus : BOOLEAN;
- Qdoit : BOOLEAN;
-
-
- (* Structured *) CONST
-
- P : ARRAY [ 1 .. 29 ] OF REAL =
- ( 4.12084318584770E+00 ,
- 8.56898206283132E+01 ,
- 2.43175243524421E+02 ,
- -2.61721858385614E+02 ,
- -9.22261372880152E+02 ,
- -5.17638349802321E+02 ,
- -7.74106407133295E+01 ,
- -2.20884399721618E+00 ,
-
- 5.15505761764082E+00 ,
- 3.77510679797217E+02 ,
- 5.26898325591498E+03 ,
- 1.95536055406304E+04 ,
- 1.20431738098716E+04 ,
- -2.06482942053253E+04 ,
- -1.50863022876672E+04 ,
- -1.51383183411507E+03 ,
-
- -1.03770165173298E+04 ,
- -9.82710228142049E+05 ,
- -1.97183011586092E+07 ,
- -8.73167543823839E+07 ,
- 1.11938535429986E+08 ,
- 4.81807710277363E+08 ,
- -2.44832176903288E+08 ,
- -2.40798698017337E+08 ,
-
- 8.06588089900001E-04 ,
- -5.94997310888900E-04 ,
- 7.93650067542790E-04 ,
- -2.77777777688189E-03 ,
- 8.33333333333330E-02 );
-
- Q : ARRAY [ 1 .. 24 ] OF REAL =
- ( 1.00000000000000E+00 ,
- 4.56467718758591E+01 ,
- 3.77837248482394E+02 ,
- 9.51323597679706E+02 ,
- 8.46075536202078E+02 ,
- 2.62308347026946E+02 ,
- 2.44351966250631E+01 ,
- 4.09779292109262E-01 ,
-
- 1.00000000000000E+00 ,
- 1.28909318901296E+02 ,
- 3.03990304143943E+03 ,
- 2.20295621441566E+04 ,
- 5.71202553960250E+04 ,
- 5.26228638384119E+04 ,
- 1.44020903717009E+04 ,
- 6.98327414057351E+02 ,
-
- 1.00000000000000E+00 ,
- -2.01527519550048E+03 ,
- -3.11406284734067E+05 ,
- -1.04857758304994E+07 ,
- -1.11925411626332E+08 ,
- -4.04435928291436E+08 ,
- -4.35370714804374E+08 ,
- -7.90261111418763E+07 );
-
- BEGIN (* ALGama *)
-
-
- (* Initialize *)
-
- Algval := Rinf;
- Scale := 1.0;
- Alinc := 0.0;
- Frac := 0.0;
- Rarg := Arg;
- Iof := 1;
- Qminus := FALSE;
- Qdoit := TRUE;
- (* Adjust for negative argument *)
-
- IF( Rarg < 0.0 ) THEN
- BEGIN
-
- Qminus := TRUE;
- Rarg := -Rarg;
- Top := Int( Rarg );
- Bot := 1.0;
-
- IF( ( INT( Top / 2.0 ) * 2.0 ) = 0.0 ) THEN Bot := -1.0;
-
- Top := Rarg - Top;
-
- IF( Top = 0.0 ) THEN
- Qdoit := FALSE
- ELSE
- BEGIN
- Frac := Bot * PI / SIN( Top * PI );
- Rarg := Rarg + 1.0;
- Frac := LN( ABS( Frac ) );
- END;
-
- END;
- (* Choose approximation interval *)
- (* based upon argument range *)
-
- IF( Rarg = 0.0 ) THEN
- Qdoit := FALSE
-
- ELSE IF( Rarg <= 0.5 ) THEN
- BEGIN
-
- Alinc := -LN( Rarg );
- Scale := Rarg;
- Rarg := Rarg + 1.0;
-
- IF( Scale < Zeta ) THEN
- BEGIN
- Algval := Alinc;
- Qdoit := FALSE;
- END;
-
- END
-
- ELSE IF ( Rarg <= 1.5 ) THEN
- Scale := Rarg - 1.0
-
- ELSE IF( Rarg <= 4.0 ) THEN
- BEGIN
- Scale := Rarg - 2.0;
- Iof := 9;
- END
-
- ELSE IF( Rarg <= 12.0 ) THEN
- Iof := 17
-
- ELSE IF( Rarg <= RMAX ) THEN
- BEGIN
-
- Alinc := ( Rarg - 0.5 ) * LN( Rarg ) - Rarg + Xln2sp;
- Scale := 1.0 / Rarg;
- Rarg := Scale * Scale;
-
- Top := P[ 25 ];
-
- FOR I := 26 TO 29 DO
- Top := Top * Rarg + P[ I ];
-
- Algval := Scale * Top + Alinc;
-
- Qdoit := FALSE;
-
- END;
-
- (* Common evaluation code for Arg <= 12. *)
- (* Horner's method is used, which seems *)
- (* to give better accuracy than *)
- (* continued fractions. *)
-
- IF Qdoit THEN
- BEGIN
-
- Ilo := Iof + 1;
- Ihi := Iof + 7;
-
- Top := P[ Iof ];
- Bot := Q[ Iof ];
-
- FOR I := Ilo TO Ihi DO
- BEGIN
- Top := Top * Rarg + P[ I ];
- Bot := Bot * Rarg + Q[ I ];
- END;
-
- Algval := Scale * ( Top / Bot ) + Alinc;
-
- END;
-
- IF( Qminus ) THEN Algval := Frac - Algval;
-
- ALGama := Algval;
-
- END (* ALGama *);