/* gammaf.c
*
* Gamma function
*
*
*
* SYNOPSIS :
*
* float x , y , gammaf ( ) ;
* extern int sgngamf ;
*
* y = gammaf ( x ) ;
*
*
*
* DESCRIPTION :
*
* Returns gamma function of the argument . The result is
* correctly signed , and the sign ( + 1 or - 1 ) is also
* returned in a global ( extern ) variable named sgngamf .
* This same variable is also filled in by the logarithmic
* gamma function lgam ( ) .
*
* Arguments between 0 and 10 are reduced by recurrence and the
* function is approximated by a polynomial function covering
* the interval ( 2 , 3 ) . Large arguments are handled by Stirling ' s
* formula . Negative arguments are made positive using
* a reflection formula .
*
*
* ACCURACY :
*
* Relative error :
* arithmetic domain # trials peak rms
* IEEE 0 , - 33 100 , 000 5 . 7 e - 7 1 . 0 e - 7
* IEEE - 33 , 0 100 , 000 6 . 1 e - 7 1 . 2 e - 7
*
*
*/
/* lgamf()
*
* Natural logarithm of gamma function
*
*
*
* SYNOPSIS :
*
* float x , y , lgamf ( ) ;
* extern int sgngamf ;
*
* y = lgamf ( x ) ;
*
*
*
* DESCRIPTION :
*
* Returns the base e ( 2 . 718 . . . ) logarithm of the absolute
* value of the gamma function of the argument .
* The sign ( + 1 or - 1 ) of the gamma function is returned in a
* global ( extern ) variable named sgngamf .
*
* For arguments greater than 6 . 5 , the logarithm of the gamma
* function is approximated by the logarithmic version of
* Stirling ' s formula . Arguments between 0 and + 6 . 5 are reduced by
* by recurrence to the interval [ . 75 , 1 . 25 ] or [ 1 . 5 , 2 . 5 ] of a rational
* approximation . The cosecant reflection formula is employed for
* arguments less than zero .
*
* Arguments greater than MAXLGM = 2 . 035093 e36 return MAXNUM and an
* error message .
*
*
*
* ACCURACY :
*
*
*
* arithmetic domain # trials peak rms
* IEEE - 100 , + 100 500 , 000 7 . 4 e - 7 6 . 8 e - 8
* The error criterion was relative when the function magnitude
* was greater than one but absolute when it was less than one .
* The routine has low relative error for positive arguments .
*
* The following test used the relative error criterion .
* IEEE - 2 , + 3 100000 4 . 0 e - 7 5 . 6 e - 8
*
*/
/* gamma.c */
/* gamma function */
/*
Cephes Math Library Release 2 . 7 : July , 1998
Copyright 1984 , 1987 , 1989 , 1992 , 1998 by Stephen L . Moshier
*/
#include "mconf.h"
/* define MAXGAM 34.84425627277176174 */
/* Stirling's formula for the gamma function
* gamma ( x ) = sqrt ( 2 pi ) x ^ ( x - . 5 ) exp ( - x ) ( 1 + 1 / x P ( 1 / x ) )
* . 028 < 1 / x < . 1
* relative error < 1 . 9 e - 11
*/
static float STIR[] = {
-2 .705194986674176 E-003 ,
3 .473255786154910 E-003 ,
8 .333331788340907 E-002 ,
};
static float MAXSTIR = 26 .77 ;
static float SQTPIF = 2 .50662827463100050242 ; /* sqrt( 2 pi ) */
int sgngamf = 0 ;
extern int sgngamf;
extern float MAXLOGF, MAXNUMF, PIF;
#ifdef ANSIC
float expf(float );
float logf(float );
float powf( float , float );
float sinf(float );
float gammaf(float );
float floorf(float );
static float stirf(float );
float polevlf( float , float *, int );
float p1evlf( float , float *, int );
#else
float expf(), logf(), powf(), sinf(), floorf();
float polevlf(), p1evlf();
static float stirf();
#endif
/* Gamma function computed by Stirling's formula,
* sqrt ( 2 pi ) x ^ ( x - . 5 ) exp ( - x ) ( 1 + 1 / x P ( 1 / x ) )
* The polynomial STIR is valid for 33 < = x < = 172 .
*/
#ifdef ANSIC
static float stirf( float xx )
#else
static float stirf(xx)
double xx;
#endif
{
float x, y, w, v;
x = xx;
w = 1 .0 /x;
w = 1 .0 + w * polevlf( w, STIR, 2 );
y = expf( -x );
if ( x > MAXSTIR )
{ /* Avoid overflow in pow() */
v = powf( x, 0 .5 * x - 0 .25 );
y *= v;
y *= v;
}
else
{
y = powf( x, x - 0 .5 ) * y;
}
y = SQTPIF * y * w;
return ( y );
}
/* gamma(x+2), 0 < x < 1 */
static float P[] = {
1 .536830450601906 E-003 ,
5 .397581592950993 E-003 ,
4 .130370201859976 E-003 ,
7 .232307985516519 E-002 ,
8 .203960091619193 E-002 ,
4 .117857447645796 E-001 ,
4 .227867745131584 E-001 ,
9 .999999822945073 E-001 ,
};
#ifdef ANSIC
float gammaf( float xx )
#else
float gammaf(xx)
double xx;
#endif
{
float p, q, x, z, nz;
int i, direction, negative;
x = xx;
sgngamf = 1 ;
negative = 0 ;
nz = 0 .0 ;
if ( x < 0 .0 )
{
negative = 1 ;
q = -x;
p = floorf(q);
if ( p == q )
goto goverf;
i = p;
if ( (i & 1 ) == 0 )
sgngamf = -1 ;
nz = q - p;
if ( nz > 0 .5 )
{
p += 1 .0 ;
nz = q - p;
}
nz = q * sinf( PIF * nz );
if ( nz == 0 .0 )
{
goverf:
mtherr( "gamma" , OVERFLOW );
return ( sgngamf * MAXNUMF);
}
if ( nz < 0 )
nz = -nz;
x = q;
}
if ( x >= 10 .0 )
{
z = stirf(x);
}
if ( x < 2 .0 )
direction = 1 ;
else
direction = 0 ;
z = 1 .0 ;
while ( x >= 3 .0 )
{
x -= 1 .0 ;
z *= x;
}
/*
while ( x < 0 . 0 )
{
if ( x > - 1 . E - 4 )
goto small ;
z * = x ;
x + = 1 . 0 ;
}
*/
while ( x < 2 .0 )
{
if ( x < 1 .e-4 )
goto small;
z *=x;
x += 1 .0 ;
}
if ( direction )
z = 1 .0 /z;
if ( x == 2 .0 )
return (z);
x -= 2 .0 ;
p = z * polevlf( x, P, 7 );
gdone:
if ( negative )
{
p = sgngamf * PIF/(nz * p );
}
return (p);
small:
if ( x == 0 .0 )
{
mtherr( "gamma" , SING );
return ( MAXNUMF );
}
else
{
p = z / ((1 .0 + 0 .5772156649015329 * x) * x);
goto gdone;
}
}
/* log gamma(x+2), -.5 < x < .5 */
static float B[] = {
6 .055172732649237 E-004 ,
-1 .311620815545743 E-003 ,
2 .863437556468661 E-003 ,
-7 .366775108654962 E-003 ,
2 .058355474821512 E-002 ,
-6 .735323259371034 E-002 ,
3 .224669577325661 E-001 ,
4 .227843421859038 E-001
};
/* log gamma(x+1), -.25 < x < .25 */
static float C[] = {
1 .369488127325832 E-001 ,
-1 .590086327657347 E-001 ,
1 .692415923504637 E-001 ,
-2 .067882815621965 E-001 ,
2 .705806208275915 E-001 ,
-4 .006931650563372 E-001 ,
8 .224670749082976 E-001 ,
-5 .772156501719101 E-001
};
/* log( sqrt( 2*pi ) ) */
static float LS2PI = 0 .91893853320467274178 ;
#define MAXLGM 2 .035093 e36
static float PIINV = 0 .318309886183790671538 ;
/* Logarithm of gamma function */
#ifdef ANSIC
float lgamf( float xx )
#else
float lgamf(xx)
double xx;
#endif
{
float p, q, w, z, x;
float nx, tx;
int i, direction;
sgngamf = 1 ;
x = xx;
if ( x < 0 .0 )
{
q = -x;
w = lgamf(q); /* note this modifies sgngam! */
p = floorf(q);
if ( p == q )
goto loverf;
i = p;
if ( (i & 1 ) == 0 )
sgngamf = -1 ;
else
sgngamf = 1 ;
z = q - p;
if ( z > 0 .5 )
{
p += 1 .0 ;
z = p - q;
}
z = q * sinf( PIF * z );
if ( z == 0 .0 )
goto loverf;
z = -logf( PIINV*z ) - w;
return ( z );
}
if ( x < 6 .5 )
{
direction = 0 ;
z = 1 .0 ;
tx = x;
nx = 0 .0 ;
if ( x >= 1 .5 )
{
while ( tx > 2 .5 )
{
nx -= 1 .0 ;
tx = x + nx;
z *=tx;
}
x += nx - 2 .0 ;
iv1r5:
p = x * polevlf( x, B, 7 );
goto cont;
}
if ( x >= 1 .25 )
{
z *= x;
x -= 1 .0 ; /* x + 1 - 2 */
direction = 1 ;
goto iv1r5;
}
if ( x >= 0 .75 )
{
x -= 1 .0 ;
p = x * polevlf( x, C, 7 );
q = 0 .0 ;
goto contz;
}
while ( tx < 1 .5 )
{
if ( tx == 0 .0 )
goto loverf;
z *=tx;
nx += 1 .0 ;
tx = x + nx;
}
direction = 1 ;
x += nx - 2 .0 ;
p = x * polevlf( x, B, 7 );
cont:
if ( z < 0 .0 )
{
sgngamf = -1 ;
z = -z;
}
else
{
sgngamf = 1 ;
}
q = logf(z);
if ( direction )
q = -q;
contz:
return ( p + q );
}
if ( x > MAXLGM )
{
loverf:
mtherr( "lgamf" , OVERFLOW );
return ( sgngamf * MAXNUMF );
}
/* Note, though an asymptotic formula could be used for x >= 3,
* there is cancellation error in the following if x < 6.5. */
q = LS2PI - x;
q += ( x - 0 .5 ) * logf(x);
if ( x <= 1 .0 e4 )
{
z = 1 .0 /x;
p = z * z;
q += (( 6 .789774945028216 E-004 * p
- 2 .769887652139868 E-003 ) * p
+ 8 .333316229807355 E-002 ) * z;
}
return ( q );
}
Messung V0.5 in Prozent C=96 H=80 G=88
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-14)
¤
*© Formatika GbR, Deutschland