| /** |
| * 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 (INFINITY); |
| #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)); |
| } |
| |