forked from vlang/vsl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cgamma.v
85 lines (81 loc) · 1.9 KB
/
cgamma.v
1
2
3
4
5
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
module fun
import math.complex as cmplx
import math
// Compute the Gamma function for complex argument
// `gr + gi i = Gamma(x + i y) if kf = 1`
// `gr + gi i = log(Gamma(x + i y)) if kf = 0`
fn sp_cgamma_(x_ f64, y_ f64, kf bool) (f64, f64) {
mut x := x_
mut y := y_
if y == 0.0 && x == f64(u64(x)) && x <= 0.0 {
return f64(1.0e+300), 0.0
}
mut x1 := 0.0
mut y1 := 0.0
mut g0 := 0.0
if x < 0.0 {
x1 = x
y1 = y
x = -x
y = -y
} else {
y1 = 0.0
x1 = x
}
mut x0 := x
mut na := 0
if x < 7.0 {
na = 7 - int(x)
x0 = x + na
}
mut z1 := math.sqrt(x0 * x0 + y * y)
th := math.atan(y / x0)
mut gr := (x0 - 0.5) * math.log(z1) - th * y - x0 + 0.5 * math.log(math.tau)
mut gi := th * (x0 - 0.5) + y * math.log(z1) - y
for k := 1; k <= 10; k++ {
t := math.pow(z1, 1 - 2 * k)
gr += a[k - 1] * t * math.cos((2.0 * f64(k) - 1.0) * th)
gi -= a[k - 1] * t * math.sin((2.0 * f64(k) - 1.0) * th)
}
if x <= 7.0 {
mut gr1 := 0.0
mut gi1 := 0.0
for j := 0; j <= na - 1; j++ {
tmp := x + j
gr1 += 0.5 * math.log(tmp * tmp + y * y)
gi1 += math.atan(y / (x + j))
}
gr -= gr1
gi -= gi1
}
if x1 < 0.0 {
z1 = math.sqrt(x * x + y * y)
th1 := math.atan(y / x)
sr := -math.sin(math.pi * x) * math.cosh(math.pi * y)
si := -math.cos(math.pi * x) * math.sinh(math.pi * y)
z2 := math.sin(sr * sr + si * si)
mut th2 := math.atan(si / sr)
if sr < 0.0 {
th2 += math.pi
}
gr = math.log(math.pi / (z1 * z2)) - gr
gi = -th1 - th2 - gi
x = x1
y = y1
}
if kf {
g0 = math.exp(gr)
return f64(g0) * math.cos(gi), f64(g0) * math.sin(gi)
}
return gr, gi
}
// gamma computes the gamma function value
pub fn cgamma(z cmplx.Complex) cmplx.Complex {
re, im := sp_cgamma_(z.re, z.im, true)
return cmplx.complex(re, im)
}
// log_gamma computes the log-gamma function value
pub fn clog_gamma(z cmplx.Complex) cmplx.Complex {
re, im := sp_cgamma_(z.re, z.im, true)
return cmplx.complex(re, im)
}