/mingw-w64-v2.0.999/mingw/mingw-w64-crt/math/lgammaf.c
# · C · 188 lines · 159 code · 16 blank · 13 comment · 22 complexity · 7bf85d4b5c24c75088533798406ae410 MD5 · raw file
- /**
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is part of the w64 mingw-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)
- {
- int local_sgngamf = 0;
- return (__lgammaf_r(x, &local_sgngamf));
- }