float tgammaf(float x) { int sign; float y; y = exp(__lgammaf_r(x, &sign)); if (sign < 0) y = -y; return y; }
float lgammaf(float x) { return __lgammaf_r(x, &__signgam); }
float __lgammaf_r( float x, int* sgngamf ) { float p, q, w, z; float nx, tx; int i, direction; *sgngamf = 1; #ifdef NANS if( isnan(x) ) return(x); #endif #ifdef INFINITIES if( !isfinite(x) ) return(x); #endif if( x < 0.0 ) { q = -x; w = __lgammaf_r(q, sgngamf); /* note this modifies sgngam! */ p = floorf(q); if( p == q ) { lgsing: _SET_ERRNO(EDOM); mtherr( "lgamf", SING ); #ifdef INFINITIES return (INFINITYF); #else return( *sgngamf * MAXNUMF ); #endif } 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 lgsing; 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 lgsing; 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 ) { _SET_ERRNO(ERANGE); mtherr( "lgamf", OVERFLOW ); #ifdef INFINITIES return( *sgngamf * INFINITYF ); #else return( *sgngamf * MAXNUMF ); #endif } /* 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.0e4 ) { z = 1.0/x; p = z * z; q += (( 6.789774945028216E-004 * p - 2.769887652139868E-003 ) * p + 8.333316229807355E-002 ) * z; } return( q ); }
float lgammaf(float x) { int local_sgngamf=0; return (__lgammaf_r(x, &local_sgngamf)); }
/* This is the C99 version */ float lgammaf(float x) { return (__lgammaf_r(x, &signgam)); }