Source file
src/math/lgamma.go
1
2
3
4
5 package math
6
7
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 var _lgamA = [...]float64{
92 7.72156649015328655494e-02,
93 3.22467033424113591611e-01,
94 6.73523010531292681824e-02,
95 2.05808084325167332806e-02,
96 7.38555086081402883957e-03,
97 2.89051383673415629091e-03,
98 1.19270763183362067845e-03,
99 5.10069792153511336608e-04,
100 2.20862790713908385557e-04,
101 1.08011567247583939954e-04,
102 2.52144565451257326939e-05,
103 4.48640949618915160150e-05,
104 }
105 var _lgamR = [...]float64{
106 1.0,
107 1.39200533467621045958e+00,
108 7.21935547567138069525e-01,
109 1.71933865632803078993e-01,
110 1.86459191715652901344e-02,
111 7.77942496381893596434e-04,
112 7.32668430744625636189e-06,
113 }
114 var _lgamS = [...]float64{
115 -7.72156649015328655494e-02,
116 2.14982415960608852501e-01,
117 3.25778796408930981787e-01,
118 1.46350472652464452805e-01,
119 2.66422703033638609560e-02,
120 1.84028451407337715652e-03,
121 3.19475326584100867617e-05,
122 }
123 var _lgamT = [...]float64{
124 4.83836122723810047042e-01,
125 -1.47587722994593911752e-01,
126 6.46249402391333854778e-02,
127 -3.27885410759859649565e-02,
128 1.79706750811820387126e-02,
129 -1.03142241298341437450e-02,
130 6.10053870246291332635e-03,
131 -3.68452016781138256760e-03,
132 2.25964780900612472250e-03,
133 -1.40346469989232843813e-03,
134 8.81081882437654011382e-04,
135 -5.38595305356740546715e-04,
136 3.15632070903625950361e-04,
137 -3.12754168375120860518e-04,
138 3.35529192635519073543e-04,
139 }
140 var _lgamU = [...]float64{
141 -7.72156649015328655494e-02,
142 6.32827064025093366517e-01,
143 1.45492250137234768737e+00,
144 9.77717527963372745603e-01,
145 2.28963728064692451092e-01,
146 1.33810918536787660377e-02,
147 }
148 var _lgamV = [...]float64{
149 1.0,
150 2.45597793713041134822e+00,
151 2.12848976379893395361e+00,
152 7.69285150456672783825e-01,
153 1.04222645593369134254e-01,
154 3.21709242282423911810e-03,
155 }
156 var _lgamW = [...]float64{
157 4.18938533204672725052e-01,
158 8.33333333333329678849e-02,
159 -2.77777777728775536470e-03,
160 7.93650558643019558500e-04,
161 -5.95187557450339963135e-04,
162 8.36339918996282139126e-04,
163 -1.63092934096575273989e-03,
164 }
165
166
167
168
169
170
171
172
173
174
175 func Lgamma(x float64) (lgamma float64, sign int) {
176 const (
177 Ymin = 1.461632144968362245
178 Two52 = 1 << 52
179 Two53 = 1 << 53
180 Two58 = 1 << 58
181 Tiny = 1.0 / (1 << 70)
182 Tc = 1.46163214496836224576e+00
183 Tf = -1.21486290535849611461e-01
184
185 Tt = -3.63867699703950536541e-18
186 )
187
188 sign = 1
189 switch {
190 case IsNaN(x):
191 lgamma = x
192 return
193 case IsInf(x, 0):
194 lgamma = x
195 return
196 case x == 0:
197 lgamma = Inf(1)
198 return
199 }
200
201 neg := false
202 if x < 0 {
203 x = -x
204 neg = true
205 }
206
207 if x < Tiny {
208 if neg {
209 sign = -1
210 }
211 lgamma = -Log(x)
212 return
213 }
214 var nadj float64
215 if neg {
216 if x >= Two52 {
217 lgamma = Inf(1)
218 return
219 }
220 t := sinPi(x)
221 if t == 0 {
222 lgamma = Inf(1)
223 return
224 }
225 nadj = Log(Pi / Abs(t*x))
226 if t < 0 {
227 sign = -1
228 }
229 }
230
231 switch {
232 case x == 1 || x == 2:
233 lgamma = 0
234 return
235 case x < 2:
236 var y float64
237 var i int
238 if x <= 0.9 {
239 lgamma = -Log(x)
240 switch {
241 case x >= (Ymin - 1 + 0.27):
242 y = 1 - x
243 i = 0
244 case x >= (Ymin - 1 - 0.27):
245 y = x - (Tc - 1)
246 i = 1
247 default:
248 y = x
249 i = 2
250 }
251 } else {
252 lgamma = 0
253 switch {
254 case x >= (Ymin + 0.27):
255 y = 2 - x
256 i = 0
257 case x >= (Ymin - 0.27):
258 y = x - Tc
259 i = 1
260 default:
261 y = x - 1
262 i = 2
263 }
264 }
265 switch i {
266 case 0:
267 z := y * y
268 p1 := _lgamA[0] + z*(_lgamA[2]+z*(_lgamA[4]+z*(_lgamA[6]+z*(_lgamA[8]+z*_lgamA[10]))))
269 p2 := z * (_lgamA[1] + z*(+_lgamA[3]+z*(_lgamA[5]+z*(_lgamA[7]+z*(_lgamA[9]+z*_lgamA[11])))))
270 p := y*p1 + p2
271 lgamma += (p - 0.5*y)
272 case 1:
273 z := y * y
274 w := z * y
275 p1 := _lgamT[0] + w*(_lgamT[3]+w*(_lgamT[6]+w*(_lgamT[9]+w*_lgamT[12])))
276 p2 := _lgamT[1] + w*(_lgamT[4]+w*(_lgamT[7]+w*(_lgamT[10]+w*_lgamT[13])))
277 p3 := _lgamT[2] + w*(_lgamT[5]+w*(_lgamT[8]+w*(_lgamT[11]+w*_lgamT[14])))
278 p := z*p1 - (Tt - w*(p2+y*p3))
279 lgamma += (Tf + p)
280 case 2:
281 p1 := y * (_lgamU[0] + y*(_lgamU[1]+y*(_lgamU[2]+y*(_lgamU[3]+y*(_lgamU[4]+y*_lgamU[5])))))
282 p2 := 1 + y*(_lgamV[1]+y*(_lgamV[2]+y*(_lgamV[3]+y*(_lgamV[4]+y*_lgamV[5]))))
283 lgamma += (-0.5*y + p1/p2)
284 }
285 case x < 8:
286 i := int(x)
287 y := x - float64(i)
288 p := y * (_lgamS[0] + y*(_lgamS[1]+y*(_lgamS[2]+y*(_lgamS[3]+y*(_lgamS[4]+y*(_lgamS[5]+y*_lgamS[6]))))))
289 q := 1 + y*(_lgamR[1]+y*(_lgamR[2]+y*(_lgamR[3]+y*(_lgamR[4]+y*(_lgamR[5]+y*_lgamR[6])))))
290 lgamma = 0.5*y + p/q
291 z := 1.0
292 switch i {
293 case 7:
294 z *= (y + 6)
295 fallthrough
296 case 6:
297 z *= (y + 5)
298 fallthrough
299 case 5:
300 z *= (y + 4)
301 fallthrough
302 case 4:
303 z *= (y + 3)
304 fallthrough
305 case 3:
306 z *= (y + 2)
307 lgamma += Log(z)
308 }
309 case x < Two58:
310 t := Log(x)
311 z := 1 / x
312 y := z * z
313 w := _lgamW[0] + z*(_lgamW[1]+y*(_lgamW[2]+y*(_lgamW[3]+y*(_lgamW[4]+y*(_lgamW[5]+y*_lgamW[6])))))
314 lgamma = (x-0.5)*(t-1) + w
315 default:
316 lgamma = x * (Log(x) - 1)
317 }
318 if neg {
319 lgamma = nadj - lgamma
320 }
321 return
322 }
323
324
325 func sinPi(x float64) float64 {
326 const (
327 Two52 = 1 << 52
328 Two53 = 1 << 53
329 )
330 if x < 0.25 {
331 return -Sin(Pi * x)
332 }
333
334
335 z := Floor(x)
336 var n int
337 if z != x {
338 x = Mod(x, 2)
339 n = int(x * 4)
340 } else {
341 if x >= Two53 {
342 x = 0
343 n = 0
344 } else {
345 if x < Two52 {
346 z = x + Two52
347 }
348 n = int(1 & Float64bits(z))
349 x = float64(n)
350 n <<= 2
351 }
352 }
353 switch n {
354 case 0:
355 x = Sin(Pi * x)
356 case 1, 2:
357 x = Cos(Pi * (0.5 - x))
358 case 3, 4:
359 x = Sin(Pi * (1 - x))
360 case 5, 6:
361 x = -Cos(Pi * (x - 1.5))
362 default:
363 x = Sin(Pi * (x - 2))
364 }
365 return -x
366 }
367
View as plain text