1
2
3
4
5 package math
6
7 8 9
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
92
93
94
95
96
97
98
99 func Lgamma(x float64) (lgamma float64, sign int) {
100 const (
101 Ymin = 1.461632144968362245
102 Two52 = 1 << 52
103 Two53 = 1 << 53
104 Two58 = 1 << 58
105 Tiny = 1.0 / (1 << 70)
106 A0 = 7.72156649015328655494e-02
107 A1 = 3.22467033424113591611e-01
108 A2 = 6.73523010531292681824e-02
109 A3 = 2.05808084325167332806e-02
110 A4 = 7.38555086081402883957e-03
111 A5 = 2.89051383673415629091e-03
112 A6 = 1.19270763183362067845e-03
113 A7 = 5.10069792153511336608e-04
114 A8 = 2.20862790713908385557e-04
115 A9 = 1.08011567247583939954e-04
116 A10 = 2.52144565451257326939e-05
117 A11 = 4.48640949618915160150e-05
118 Tc = 1.46163214496836224576e+00
119 Tf = -1.21486290535849611461e-01
120
121 Tt = -3.63867699703950536541e-18
122 T0 = 4.83836122723810047042e-01
123 T1 = -1.47587722994593911752e-01
124 T2 = 6.46249402391333854778e-02
125 T3 = -3.27885410759859649565e-02
126 T4 = 1.79706750811820387126e-02
127 T5 = -1.03142241298341437450e-02
128 T6 = 6.10053870246291332635e-03
129 T7 = -3.68452016781138256760e-03
130 T8 = 2.25964780900612472250e-03
131 T9 = -1.40346469989232843813e-03
132 T10 = 8.81081882437654011382e-04
133 T11 = -5.38595305356740546715e-04
134 T12 = 3.15632070903625950361e-04
135 T13 = -3.12754168375120860518e-04
136 T14 = 3.35529192635519073543e-04
137 U0 = -7.72156649015328655494e-02
138 U1 = 6.32827064025093366517e-01
139 U2 = 1.45492250137234768737e+00
140 U3 = 9.77717527963372745603e-01
141 U4 = 2.28963728064692451092e-01
142 U5 = 1.33810918536787660377e-02
143 V1 = 2.45597793713041134822e+00
144 V2 = 2.12848976379893395361e+00
145 V3 = 7.69285150456672783825e-01
146 V4 = 1.04222645593369134254e-01
147 V5 = 3.21709242282423911810e-03
148 S0 = -7.72156649015328655494e-02
149 S1 = 2.14982415960608852501e-01
150 S2 = 3.25778796408930981787e-01
151 S3 = 1.46350472652464452805e-01
152 S4 = 2.66422703033638609560e-02
153 S5 = 1.84028451407337715652e-03
154 S6 = 3.19475326584100867617e-05
155 R1 = 1.39200533467621045958e+00
156 R2 = 7.21935547567138069525e-01
157 R3 = 1.71933865632803078993e-01
158 R4 = 1.86459191715652901344e-02
159 R5 = 7.77942496381893596434e-04
160 R6 = 7.32668430744625636189e-06
161 W0 = 4.18938533204672725052e-01
162 W1 = 8.33333333333329678849e-02
163 W2 = -2.77777777728775536470e-03
164 W3 = 7.93650558643019558500e-04
165 W4 = -5.95187557450339963135e-04
166 W5 = 8.36339918996282139126e-04
167 W6 = -1.63092934096575273989e-03
168 )
169
170
171
172 sign = 1
173 switch {
174 case x != x:
175 lgamma = x
176 return
177 case x < -MaxFloat64 || x > MaxFloat64:
178 lgamma = x
179 return
180 case x == 0:
181 lgamma = Inf(1)
182 return
183 }
184
185 neg := false
186 if x < 0 {
187 x = -x
188 neg = true
189 }
190
191 if x < Tiny {
192 if neg {
193 sign = -1
194 }
195 lgamma = -Log(x)
196 return
197 }
198 var nadj float64
199 if neg {
200 if x >= Two52 {
201 lgamma = Inf(1)
202 return
203 }
204 t := sinPi(x)
205 if t == 0 {
206 lgamma = Inf(1)
207 return
208 }
209 nadj = Log(Pi / Fabs(t*x))
210 if t < 0 {
211 sign = -1
212 }
213 }
214
215 switch {
216 case x == 1 || x == 2:
217 lgamma = 0
218 return
219 case x < 2:
220 var y float64
221 var i int
222 if x <= 0.9 {
223 lgamma = -Log(x)
224 switch {
225 case x >= (Ymin - 1 + 0.27):
226 y = 1 - x
227 i = 0
228 case x >= (Ymin - 1 - 0.27):
229 y = x - (Tc - 1)
230 i = 1
231 default:
232 y = x
233 i = 2
234 }
235 } else {
236 lgamma = 0
237 switch {
238 case x >= (Ymin + 0.27):
239 y = 2 - x
240 i = 0
241 case x >= (Ymin - 0.27):
242 y = x - Tc
243 i = 1
244 default:
245 y = x - 1
246 i = 2
247 }
248 }
249 switch i {
250 case 0:
251 z := y * y
252 p1 := A0 + z*(A2+z*(A4+z*(A6+z*(A8+z*A10))))
253 p2 := z * (A1 + z*(A3+z*(A5+z*(A7+z*(A9+z*A11)))))
254 p := y*p1 + p2
255 lgamma += (p - 0.5*y)
256 case 1:
257 z := y * y
258 w := z * y
259 p1 := T0 + w*(T3+w*(T6+w*(T9+w*T12)))
260 p2 := T1 + w*(T4+w*(T7+w*(T10+w*T13)))
261 p3 := T2 + w*(T5+w*(T8+w*(T11+w*T14)))
262 p := z*p1 - (Tt - w*(p2+y*p3))
263 lgamma += (Tf + p)
264 case 2:
265 p1 := y * (U0 + y*(U1+y*(U2+y*(U3+y*(U4+y*U5)))))
266 p2 := 1 + y*(V1+y*(V2+y*(V3+y*(V4+y*V5))))
267 lgamma += (-0.5*y + p1/p2)
268 }
269 case x < 8:
270 i := int(x)
271 y := x - float64(i)
272 p := y * (S0 + y*(S1+y*(S2+y*(S3+y*(S4+y*(S5+y*S6))))))
273 q := 1 + y*(R1+y*(R2+y*(R3+y*(R4+y*(R5+y*R6)))))
274 lgamma = 0.5*y + p/q
275 z := 1.0
276 switch i {
277 case 7:
278 z *= (y + 6)
279 fallthrough
280 case 6:
281 z *= (y + 5)
282 fallthrough
283 case 5:
284 z *= (y + 4)
285 fallthrough
286 case 4:
287 z *= (y + 3)
288 fallthrough
289 case 3:
290 z *= (y + 2)
291 lgamma += Log(z)
292 }
293 case x < Two58:
294 t := Log(x)
295 z := 1 / x
296 y := z * z
297 w := W0 + z*(W1+y*(W2+y*(W3+y*(W4+y*(W5+y*W6)))))
298 lgamma = (x-0.5)*(t-1) + w
299 default:
300 lgamma = x * (Log(x) - 1)
301 }
302 if neg {
303 lgamma = nadj - lgamma
304 }
305 return
306 }
307
308
309 func sinPi(x float64) float64 {
310 const (
311 Two52 = 1 << 52
312 Two53 = 1 << 53
313 )
314 if x < 0.25 {
315 return -Sin(Pi * x)
316 }
317
318
319 z := Floor(x)
320 var n int
321 if z != x {
322 x = Fmod(x, 2)
323 n = int(x * 4)
324 } else {
325 if x >= Two53 {
326 x = 0
327 n = 0
328 } else {
329 if x < Two52 {
330 z = x + Two52
331 }
332 n = int(1 & Float64bits(z))
333 x = float64(n)
334 n <<= 2
335 }
336 }
337 switch n {
338 case 0:
339 x = Sin(Pi * x)
340 case 1, 2:
341 x = Cos(Pi * (0.5 - x))
342 case 3, 4:
343 x = Sin(Pi * (1 - x))
344 case 5, 6:
345 x = -Cos(Pi * (x - 1.5))
346 default:
347 x = Sin(Pi * (x - 2))
348 }
349 return -x
350 }