Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241852 views
1
#include <complex>
2
#include <cmath>
3
4
#include <iostream>
5
6
using namespace std;
7
8
const double log_2Pi = 1.83787706640935;
9
10
11
inline double my_norm(complex<double> z)
12
{
13
return(real(z*conj(z)));
14
}
15
16
const double bernoulli [] = {
17
1.0000000000000000000000000000,
18
-0.50000000000000000000000000000,
19
0.16666666666666666666666666667,
20
0.00000000000000000000000000000,
21
-0.033333333333333333333333333333,
22
0.00000000000000000000000000000,
23
0.023809523809523809523809523810,
24
0.00000000000000000000000000000,
25
-0.033333333333333333333333333333,
26
0.00000000000000000000000000000,
27
0.075757575757575757575757575758,
28
0.00000000000000000000000000000,
29
-0.25311355311355311355311355311,
30
0.00000000000000000000000000000,
31
1.1666666666666666666666666667,
32
0.00000000000000000000000000000,
33
-7.0921568627450980392156862745,
34
0.00000000000000000000000000000,
35
54.971177944862155388471177945,
36
0.00000000000000000000000000000,
37
-529.12424242424242424242424242,
38
0.00000000000000000000000000000,
39
6192.1231884057971014492753623,
40
0.00000000000000000000000000000,
41
-86580.253113553113553113553114,
42
0.00000000000000000000000000000,
43
1.4255171666666666666666666667e6,
44
0.00000000000000000000000000000,
45
-2.7298231067816091954022988506e7,
46
0.00000000000000000000000000000,
47
6.0158087390064236838430386817e8,
48
0.00000000000000000000000000000,
49
-1.5116315767092156862745098039e10,
50
0.00000000000000000000000000000,
51
4.2961464306116666666666666667e11,
52
0.00000000000000000000000000000,
53
-1.3711655205088332772159087949e13,
54
0.00000000000000000000000000000,
55
4.8833231897359316666666666667e14,
56
0.00000000000000000000000000000,
57
-1.9296579341940068148632668145e16,
58
0.00000000000000000000000000000,
59
8.4169304757368261500055370986e17,
60
0.00000000000000000000000000000,
61
-4.0338071854059455413076811594e19,
62
0.00000000000000000000000000000,
63
2.1150748638081991605601453901e21,
64
0.00000000000000000000000000000,
65
-1.2086626522296525934602731194e23,
66
0.00000000000000000000000000000
67
};
68
69
complex<double> log_GAMMA (complex<double> z,int n)
70
{
71
const long DIGITS = 15;
72
double M;
73
complex<double> log_G,r,r2,y;
74
75
double xx=z.real(),yy=z.imag();
76
if(xx<0) xx=-xx;
77
78
double x;
79
int i,m;
80
81
82
//assume the remainder stopping at the mth term is roughly bernoulli(2m)/(z+M)^(2m).
83
//Now bernoulli(2m) is roughly (2m)!/(2Pi)^(2m). So remainder is more or less
84
//(2m/(2ePi(z+M))^(2m). Setting 2m = Digits, we see that we need m/(ePi(z+M))
85
//to be roughly 1/10 in size, i.e. |z+M| should be roughly 10*m/(ePi)=10*Digits/(2ePi).
86
//squaring, gives us how large M should be.
87
88
//n==0 leads to |z+M| >10*2m/(2*Pi*e) with 2m=Digits. However, when we differentiate
89
//we end up with extra powers of (z+M) in the denominators, but extra (2m-1)...(2m+n-2)
90
//in the numerators. So assume further that |z+M| > 2m+n = Digits+n
91
92
if(n==0){
93
//.343 = 100./(4*Pi*Pi*exp(2.))
94
if((xx*xx+yy*yy)> .343*DIGITS*DIGITS) M=0;
95
else M=ceil(sqrt((DIGITS*DIGITS*.343-yy*yy))-xx+1);
96
}
97
else{
98
if((xx*xx+yy*yy)> .343*(DIGITS+n)*(DIGITS+n)) M=0;
99
else M=ceil(sqrt(((DIGITS+n)*(DIGITS+n)*.343-yy*yy))-xx+1);
100
}
101
102
if(n==0)
103
log_G=log_2Pi/2+(z+M-.5)*log(z+M)-(z+M);
104
else if(n==1)
105
log_G=log(z+M)-.5/(z+M);
106
else{
107
r=1;
108
for(m=1;m<=n-1;m++){
109
r=-r*(double)m/(z+M);
110
}
111
log_G=log_G-r/((double)n-1)-.5*r/(z+M);
112
}
113
114
r=1;
115
for(m=1;m<=n;m++){
116
r=-r*(double)m/(z+M);
117
}
118
r=r/(z+M);
119
120
r2=1.0/((z+M)*(z+M));
121
m=2;
122
x=my_norm(r);
123
do{
124
y=bernoulli[m]*r;
125
log_G=log_G+y/((double)m*(m-1));
126
127
r=r*((double)m+n-1)*(m+(double)n)*r2/((m-1)*(double)m);
128
m=m+2;
129
//}while(m<=DIGITS&&my_norm(r)*tolerance_sqrd<x);
130
}while(m<=DIGITS);
131
132
for(m=0;m<=M-1;m++){
133
if(n==0){
134
log_G=log_G-log(z+(double)m); //XXX might be faster to multiply and take one log,
135
//but careful about overflow errors
136
}
137
else{
138
r=1;
139
for(i=1;i<=n;i++){
140
r=-r*(double)i/(z+(double)m);
141
}
142
log_G=log_G+r/(double)n;
143
}
144
}
145
146
return log_G;
147
}
148
149
double sinc(double u, double Delta) {
150
// return (sin(pi * u * Delta)/(pi * u * Delta))
151
//
152
// If the input is very small, we use the power series expansion.
153
// Otherwise we will compute it directly.
154
155
double x = u * Delta * M_PI;
156
157
if(abs(x) < .00001) {
158
return -pow(x, 6)/5040 + pow(x, 4)/120 - pow(x, 2)/6 + 1;
159
}
160
else {
161
return sin(x)/x;
162
}
163
}
164
165
double sinc_square(double u, double Delta) {
166
// return (sin(pi * u * Delta)/(pi * u * Delta))^2
167
//
168
// If the input is very small, we use the power series expansion.
169
// Otherwise we will compute it directly.
170
171
double x = u * Delta * M_PI;
172
173
if(abs(x) < .00001) {
174
return 1 - 1.0/3.0 * pow(x, 2) + 2.0/45.0 * pow(x, 4) - 1.0/315.0 * pow(x, 6);
175
}
176
else {
177
double a = sin(x)/x;
178
return a*a;
179
}
180
}
181
182
double triangle(double u, double Delta) {
183
return (1 - abs(u/Delta))/Delta;
184
}
185
186