1 /**
2 * This file has no copyright assigned and is placed in the Public Domain.
3 * This file is part of the mingw-w64 runtime package.
4 * No warranty is given; refer to the file DISCLAIMER.PD within this package.
5 */
6 /* log gamma(x+2), -.5 < x < .5 */
7 static const float B[] = {
8 6.055172732649237E-004,
9 -1.311620815545743E-003,
10 2.863437556468661E-003,
11 -7.366775108654962E-003,
12 2.058355474821512E-002,
13 -6.735323259371034E-002,
14 3.224669577325661E-001,
15 4.227843421859038E-001
16 };
17
18 /* log gamma(x+1), -.25 < x < .25 */
19 static const float C[] = {
20 1.369488127325832E-001,
21 -1.590086327657347E-001,
22 1.692415923504637E-001,
23 -2.067882815621965E-001,
24 2.705806208275915E-001,
25 -4.006931650563372E-001,
26 8.224670749082976E-001,
27 -5.772156501719101E-001
28 };
29
30 /* log( sqrt( 2*pi ) ) */
31 static const float LS2PI = 0.91893853320467274178;
32 #define MAXLGM 2.035093e36
33 static const float PIINV = 0.318309886183790671538;
34
35 #include "cephes_mconf.h"
36
37 /* Reentrant version */
38 /* Logarithm of gamma function */
39 float __lgammaf_r(float x, int* sgngamf);
40
__lgammaf_r(float x,int * sgngamf)41 float __lgammaf_r(float x, int* sgngamf)
42 {
43 float p, q, w, z;
44 float nx, tx;
45 int i, direction;
46
47 *sgngamf = 1;
48 #ifdef NANS
49 if (isnan(x))
50 return (x);
51 #endif
52
53 #ifdef INFINITIES
54 if (!isfinite(x))
55 return (INFINITY);
56 #endif
57
58 if (x < 0.0)
59 {
60 q = -x;
61 w = __lgammaf_r(q, sgngamf); /* note this modifies sgngam! */
62 p = floorf(q);
63 if (p == q)
64 {
65 lgsing:
66 _SET_ERRNO(EDOM);
67 mtherr("lgamf", SING);
68 #ifdef INFINITIES
69 return (INFINITYF);
70 #else
71 return( *sgngamf * MAXNUMF );
72 #endif
73 }
74 i = p;
75 if ((i & 1) == 0)
76 *sgngamf = -1;
77 else
78 *sgngamf = 1;
79 z = q - p;
80 if (z > 0.5)
81 {
82 p += 1.0;
83 z = p - q;
84 }
85 z = q * sinf(PIF * z);
86 if (z == 0.0)
87 goto lgsing;
88 z = -logf(PIINV * z) - w;
89 return (z);
90 }
91
92 if (x < 6.5)
93 {
94 direction = 0;
95 z = 1.0;
96 tx = x;
97 nx = 0.0;
98 if (x >= 1.5)
99 {
100 while (tx > 2.5)
101 {
102 nx -= 1.0;
103 tx = x + nx;
104 z *=tx;
105 }
106 x += nx - 2.0;
107 iv1r5:
108 p = x * polevlf( x, B, 7 );
109 goto cont;
110 }
111 if (x >= 1.25)
112 {
113 z *= x;
114 x -= 1.0; /* x + 1 - 2 */
115 direction = 1;
116 goto iv1r5;
117 }
118 if (x >= 0.75)
119 {
120 x -= 1.0;
121 p = x * polevlf( x, C, 7 );
122 q = 0.0;
123 goto contz;
124 }
125 while (tx < 1.5)
126 {
127 if (tx == 0.0)
128 goto lgsing;
129 z *=tx;
130 nx += 1.0;
131 tx = x + nx;
132 }
133 direction = 1;
134 x += nx - 2.0;
135 p = x * polevlf(x, B, 7);
136
137 cont:
138 if (z < 0.0)
139 {
140 *sgngamf = -1;
141 z = -z;
142 }
143 else
144 {
145 *sgngamf = 1;
146 }
147 q = logf(z);
148 if (direction)
149 q = -q;
150 contz:
151 return( p + q );
152 }
153
154 if (x > MAXLGM)
155 {
156 _SET_ERRNO(ERANGE);
157 mtherr("lgamf", OVERFLOW);
158 #ifdef INFINITIES
159 return (*sgngamf * INFINITYF);
160 #else
161 return (*sgngamf * MAXNUMF);
162 #endif
163
164 }
165
166 /* Note, though an asymptotic formula could be used for x >= 3,
167 * there is cancellation error in the following if x < 6.5. */
168 q = LS2PI - x;
169 q += (x - 0.5) * logf(x);
170
171 if (x <= 1.0e4)
172 {
173 z = 1.0/x;
174 p = z * z;
175 q += (( 6.789774945028216E-004 * p
176 - 2.769887652139868E-003 ) * p
177 + 8.333316229807355E-002 ) * z;
178 }
179 return (q);
180 }
181
182 /* This is the C99 version */
lgammaf(float x)183 float lgammaf(float x)
184 {
185 return (__lgammaf_r(x, &signgam));
186 }
187
188