Source file
src/math/lgamma.go
Documentation: math
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 func Lgamma(x float64) (lgamma float64, sign int) {
175 const (
176 Ymin = 1.461632144968362245
177 Two52 = 1 << 52
178 Two53 = 1 << 53
179 Two58 = 1 << 58
180 Tiny = 1.0 / (1 << 70)
181 Tc = 1.46163214496836224576e+00
182 Tf = -1.21486290535849611461e-01
183
184 Tt = -3.63867699703950536541e-18
185 )
186
187 sign = 1
188 switch {
189 case IsNaN(x):
190 lgamma = x
191 return
192 case IsInf(x, 0):
193 lgamma = x
194 return
195 case x == 0:
196 lgamma = Inf(1)
197 return
198 }
199
200 neg := false
201 if x < 0 {
202 x = -x
203 neg = true
204 }
205
206 if x < Tiny {
207 if neg {
208 sign = -1
209 }
210 lgamma = -Log(x)
211 return
212 }
213 var nadj float64
214 if neg {
215 if x >= Two52 {
216 lgamma = Inf(1)
217 return
218 }
219 t := sinPi(x)
220 if t == 0 {
221 lgamma = Inf(1)
222 return
223 }
224 nadj = Log(Pi / Abs(t*x))
225 if t < 0 {
226 sign = -1
227 }
228 }
229
230 switch {
231 case x == 1 || x == 2:
232 lgamma = 0
233 return
234 case x < 2:
235 var y float64
236 var i int
237 if x <= 0.9 {
238 lgamma = -Log(x)
239 switch {
240 case x >= (Ymin - 1 + 0.27):
241 y = 1 - x
242 i = 0
243 case x >= (Ymin - 1 - 0.27):
244 y = x - (Tc - 1)
245 i = 1
246 default:
247 y = x
248 i = 2
249 }
250 } else {
251 lgamma = 0
252 switch {
253 case x >= (Ymin + 0.27):
254 y = 2 - x
255 i = 0
256 case x >= (Ymin - 0.27):
257 y = x - Tc
258 i = 1
259 default:
260 y = x - 1
261 i = 2
262 }
263 }
264 switch i {
265 case 0:
266 z := y * y
267 p1 := _lgamA[0] + z*(_lgamA[2]+z*(_lgamA[4]+z*(_lgamA[6]+z*(_lgamA[8]+z*_lgamA[10]))))
268 p2 := z * (_lgamA[1] + z*(+_lgamA[3]+z*(_lgamA[5]+z*(_lgamA[7]+z*(_lgamA[9]+z*_lgamA[11])))))
269 p := y*p1 + p2
270 lgamma += (p - 0.5*y)
271 case 1:
272 z := y * y
273 w := z * y
274 p1 := _lgamT[0] + w*(_lgamT[3]+w*(_lgamT[6]+w*(_lgamT[9]+w*_lgamT[12])))
275 p2 := _lgamT[1] + w*(_lgamT[4]+w*(_lgamT[7]+w*(_lgamT[10]+w*_lgamT[13])))
276 p3 := _lgamT[2] + w*(_lgamT[5]+w*(_lgamT[8]+w*(_lgamT[11]+w*_lgamT[14])))
277 p := z*p1 - (Tt - w*(p2+y*p3))
278 lgamma += (Tf + p)
279 case 2:
280 p1 := y * (_lgamU[0] + y*(_lgamU[1]+y*(_lgamU[2]+y*(_lgamU[3]+y*(_lgamU[4]+y*_lgamU[5])))))
281 p2 := 1 + y*(_lgamV[1]+y*(_lgamV[2]+y*(_lgamV[3]+y*(_lgamV[4]+y*_lgamV[5]))))
282 lgamma += (-0.5*y + p1/p2)
283 }
284 case x < 8:
285 i := int(x)
286 y := x - float64(i)
287 p := y * (_lgamS[0] + y*(_lgamS[1]+y*(_lgamS[2]+y*(_lgamS[3]+y*(_lgamS[4]+y*(_lgamS[5]+y*_lgamS[6]))))))
288 q := 1 + y*(_lgamR[1]+y*(_lgamR[2]+y*(_lgamR[3]+y*(_lgamR[4]+y*(_lgamR[5]+y*_lgamR[6])))))
289 lgamma = 0.5*y + p/q
290 z := 1.0
291 switch i {
292 case 7:
293 z *= (y + 6)
294 fallthrough
295 case 6:
296 z *= (y + 5)
297 fallthrough
298 case 5:
299 z *= (y + 4)
300 fallthrough
301 case 4:
302 z *= (y + 3)
303 fallthrough
304 case 3:
305 z *= (y + 2)
306 lgamma += Log(z)
307 }
308 case x < Two58:
309 t := Log(x)
310 z := 1 / x
311 y := z * z
312 w := _lgamW[0] + z*(_lgamW[1]+y*(_lgamW[2]+y*(_lgamW[3]+y*(_lgamW[4]+y*(_lgamW[5]+y*_lgamW[6])))))
313 lgamma = (x-0.5)*(t-1) + w
314 default:
315 lgamma = x * (Log(x) - 1)
316 }
317 if neg {
318 lgamma = nadj - lgamma
319 }
320 return
321 }
322
323
324 func sinPi(x float64) float64 {
325 const (
326 Two52 = 1 << 52
327 Two53 = 1 << 53
328 )
329 if x < 0.25 {
330 return -Sin(Pi * x)
331 }
332
333
334 z := Floor(x)
335 var n int
336 if z != x {
337 x = Mod(x, 2)
338 n = int(x * 4)
339 } else {
340 if x >= Two53 {
341 x = 0
342 n = 0
343 } else {
344 if x < Two52 {
345 z = x + Two52
346 }
347 n = int(1 & Float64bits(z))
348 x = float64(n)
349 n <<= 2
350 }
351 }
352 switch n {
353 case 0:
354 x = Sin(Pi * x)
355 case 1, 2:
356 x = Cos(Pi * (0.5 - x))
357 case 3, 4:
358 x = Sin(Pi * (1 - x))
359 case 5, 6:
360 x = -Cos(Pi * (x - 1.5))
361 default:
362 x = Sin(Pi * (x - 2))
363 }
364 return -x
365 }
366
View as plain text