/** * This file has no copyright assigned and is placed in the Public Domain. * This file is part of the mingw-w64 runtime package. * No warranty is given; refer to the file DISCLAIMER.PD within this package. */ /* log gamma(x+2), -.5 < x < .5 */ static const float B[] = { 6.055172732649237E-004, -1.311620815545743E-003, 2.863437556468661E-003, -7.366775108654962E-003, 2.058355474821512E-002, -6.735323259371034E-002, 3.224669577325661E-001, 4.227843421859038E-001 }; /* log gamma(x+1), -.25 < x < .25 */ static const float C[] = { 1.369488127325832E-001, -1.590086327657347E-001, 1.692415923504637E-001, -2.067882815621965E-001, 2.705806208275915E-001, -4.006931650563372E-001, 8.224670749082976E-001, -5.772156501719101E-001 }; /* log( sqrt( 2*pi ) ) */ static const float LS2PI = 0.91893853320467274178; #define MAXLGM 2.035093e36 static const float PIINV = 0.318309886183790671538; #include "cephes_mconf.h" /* Reentrant version */ /* Logarithm of gamma function */ float __lgammaf_r(float x, int* sgngamf); 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); } /* This is the C99 version */ float lgammaf(float x) { return (__lgammaf_r(x, &signgam)); }