flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
Li6.cpp
Go to the documentation of this file.
1// ====================================================================
2// This file is part of Polylogarithm.
3//
4// Polylogarithm is licenced under the MIT License.
5// ====================================================================
6
7#include "Li6.hpp"
8#include "complex.hpp"
9#include <cfloat>
10#include <cmath>
11
12namespace flexiblesusy {
13
14namespace {
15
16 template <typename T, int N>
17 Complex<T> horner(const Complex<T>& z, const T (&coeffs)[N]) noexcept
18 {
19 static_assert(N >= 2, "more than two coefficients required");
20
21 const T r = z.re + z.re;
22 const T s = z.re * z.re + z.im * z.im;
23 T a = coeffs[N - 1], b = coeffs[N - 2];
24
25 for (int i = N - 3; i >= 0; --i) {
26 const T t = a;
27 a = b + r * a;
28 b = coeffs[i] - s * t;
29 }
30
31 return Complex<T>(z.re*a + b, z.im*a);
32 }
33
34} // anonymous namespace
35
42std::complex<double> Li6(const std::complex<double>& z_) noexcept
43{
44 const double PI = 3.1415926535897932;
45 const double PI2 = PI*PI;
46 const double PI4 = PI2*PI2;
47 const double PI6 = PI2*PI4;
48 const double zeta6 = 1.0173430619844491;
49 const double bf[18] = {
50 1.0 , -31.0/64.0 ,
51 1.5241340877914952e-01, -3.4365555877057613e-02,
52 5.7174797239368999e-03, -6.8180453746570645e-04,
53 4.9960361948734493e-05, -4.9166051196039048e-07,
54 -3.0632975161302164e-07, 1.4414599270849095e-08,
55 3.7272438230924107e-09, -3.7300867345487607e-10,
56 -5.1246526816085832e-11, 9.0541930956636683e-12,
57 6.7381882615512517e-13, -2.1215831150303135e-13,
58 -6.8408811719011698e-15, 4.8691178462005581e-15
59 };
60
61 const Complex<double> z = { std::real(z_), std::imag(z_) };
62
63 if (z.im == 0) {
64 if (z.re == 0) {
65 return 0.0;
66 }
67 if (z.re == 1) {
68 return zeta6;
69 }
70 if (z.re == -1) {
71 return -31.0*zeta6/32.0;
72 }
73 }
74
75 const double nz = norm(z);
76 const double pz = arg(z);
77 const double lnz = std::log(nz);
78
79 if (lnz*lnz + pz*pz < 1) { // |log(z)| < 1
80 const Complex<double> u(lnz, pz); // log(z)
81 const Complex<double> u2 = u*u;
82 const double c0 = zeta6;
83 const double c1 = 1.0369277551433699; // zeta(5)
84 const double c2 = 0.54116161685556910;
85 const double c3 = 0.20034281719326571;
86 const double c4 = 0.068538919452009435;
87 const Complex<double> c5 = (137.0/60.0 - log(-u))/120.0;
88 const double c6 = -1.0/1440.0;
89
90 const double cs[5] = {
91 -1.6534391534391534e-05, 2.2964432686654909e-08,
92 -9.9413128513657614e-11, 6.6912682653423394e-13,
93 -5.7933058574392549e-15
94 };
95
96 return c0 + u * c1 +
97 u2 * (c2 + u * c3 +
98 u2 * (c4 + u * c5 +
99 u2 * (c6 +
100 u * horner(u2, cs))));
101 }
102
103 Complex<double> u(0.0, 0.0), rest(0.0, 0.0);
104 double sgn = 1;
105
106 if (nz <= 1) {
107 u = -log(1.0 - z);
108 } else { // nz > 1
109 const double arg = pz > 0.0 ? pz - PI : pz + PI;
110 const Complex<double> lmz(lnz, arg); // log(-z)
111 const Complex<double> lmz2 = lmz*lmz;
112 u = -log(1.0 - 1.0/z);
113 rest = -31.0*PI6/15120.0 + lmz2*(-7.0/720.0*PI4 + lmz2*(-1.0/144.0*PI2 - 1.0/720.0*lmz2));
114 sgn = -1;
115 }
116
117 const Complex<double> u2 = u*u;
118 const Complex<double> u4 = u2*u2;
119 const Complex<double> u8 = u4*u4;
120
121 return
122 rest + sgn * (
123 u*bf[0] +
124 u2*(bf[1] + u*bf[2]) +
125 u4*(bf[3] + u*bf[4] + u2*(bf[5] + u*bf[6])) +
126 u8*(bf[7] + u*bf[8] + u2*(bf[9] + u*bf[10]) +
127 u4*(bf[11] + u*bf[12] + u2*(bf[13] + u*bf[14]))) +
128 u8*u8*(bf[15] + u*bf[16] + u2*bf[17])
129 );
130}
131
138std::complex<long double> Li6(const std::complex<long double>& z_) noexcept
139{
140 const long double PI = 3.14159265358979323846264338327950288L;
141 const long double PI2 = PI*PI;
142 const long double PI4 = PI2*PI2;
143 const long double PI6 = PI2*PI4;
144 const long double zeta6 = 1.01734306198444913971451792979092053L;
145 const long double bf[] = {
146 1.0L,
147 -31.0L/64.0L,
148 1.52413408779149519890260631001371742e-01L,
149 -3.43655558770576131687242798353909465e-02L,
150 5.71747972393689986282578875171467764e-03L,
151 -6.81804537465706447187928669410150892e-04L,
152 4.99603619487344931145170169621327906e-05L,
153 -4.91660511960390477202530822164616726e-07L,
154 -3.06329751613021637853530304310404212e-07L,
155 1.44145992708490953612537421448012923e-08L,
156 3.72724382309241065768599245664598825e-09L,
157 -3.73008673454876072077977229159261141e-10L,
158 -5.12465268160858324340087646115722592e-11L,
159 9.05419309566366828868797447620893807e-12L,
160 6.73818826155125170776107544938009482e-13L,
161 -2.12158311503031353185279689296609530e-13L,
162 -6.84088117190116976639204518781909079e-15L,
163 4.86911784620055813206387586512917456e-15L,
164 -4.84398784998725041650889647473159420e-18L,
165 -1.10271048491074909370430302576046237e-16L,
166 3.33537969169393816624889411840735964e-18L,
167 2.47353074886413529791540987487137046e-18L,
168#if LDBL_DIG > 18
169 -1.43706164342324920216883687134737009e-19L,
170 -5.50471103350981180614826435059791109e-20L,
171 4.74677139173272249791309840662617185e-21L,
172 1.21583871780681052243739817416294433e-21L,
173 -1.41075524035618500414240309078008657e-22L,
174 -2.66388312532683465965856437677118103e-23L,
175 3.96676574286310079767900226081781935e-24L,
176 5.78216973585436153112366193481125963e-25L,
177 -1.07877780631642573172998876995922389e-25L,
178 -1.24073970867569098990147736977589145e-26L,
179 2.87041179178936017042609524684092346e-27L,
180 2.62355535630293306165747520383606820e-28L,
181 -7.52294854657541272615881214134337672e-29L,
182 -5.44017883796246961820291930722306669e-30L,
183 1.95025795325101663793862223381656999e-30L,
184 1.09784942822051879961178213597012971e-31L,
185 -5.01495835741630092074469585415763612e-32L,
186 -2.12867375043927610535633806917391780e-33L,
187 1.28159440165221259409319852281486752e-33L,
188 3.87108447330479441622204568697607460e-35L,
189 -3.25941253155837592741689642881678163e-35L,
190 -6.25269198847740581093233860701356903e-37L,
191 8.25794162051839801918004563317046685e-37L
192#endif
193 };
194
195 const Complex<long double> z = { std::real(z_), std::imag(z_) };
196
197 if (z.im == 0) {
198 if (z.re == 0) {
199 return 0.0L;
200 }
201 if (z.re == 1) {
202 return zeta6;
203 }
204 if (z.re == -1) {
205 return -31.0L*zeta6/32.0L;
206 }
207 }
208
209 const long double nz = norm(z);
210 const long double pz = arg(z);
211 const long double lnz = std::log(nz);
212
213 if (lnz*lnz + pz*pz < 1) { // |log(z)| < 1
214 const Complex<long double> u(lnz, pz); // log(z)
215 const Complex<long double> u2 = u*u;
216 const long double c0 = zeta6;
217 const long double c1 = 1.03692775514336992633136548645703417L; // zeta(5)
218 const long double c2 = 0.541161616855569095758001848270583951L;
219 const long double c3 = 0.200342817193265714233289693585241665L;
220 const long double c4 = 0.0685389194520094348530172986102510496L;
221 const Complex<long double> c5 = (137.0L/60.0L - log(-u))/120.0L;
222 const long double c6 = -1.0L/1440.0L;
223
224 const long double cs[] = {
225 -1.65343915343915343915343915343915344e-05L,
226 2.29644326866549088771310993533215755e-08L,
227 -9.94131285136576141867147158152449158e-11L,
228 6.69126826534233941641349048756456164e-13L,
229 -5.79330585743925490598570604983944731e-15L,
230 5.93014945895224312384148778345583373e-17L,
231#if LDBL_DIG > 18
232 -6.85052937218694143079665103072690062e-19L,
233 8.67589801792722939607545055256974774e-21L,
234 -1.18132150428192854833283051865852971e-22L,
235 1.70561884258584436997421138705840854e-24L,
236 -2.58484268003343989655128609060798194e-26L,
237 4.08008103922306292972099603527323696e-28L,
238 -6.66771970595289681764999062443512889e-30L,
239 1.12276996725126418754155893790528500e-31L,
240 -1.94061827643615870372790552830090522e-33L,
241 3.43209344566599308274080635472598888e-35L,
242 -6.19462586636097236736900573587284992e-37L
243#endif
244 };
245
246 return c0 + u * c1 +
247 u2 * (c2 + u * c3 +
248 u2 * (c4 + u * c5 +
249 u2 * (c6 +
250 u * horner(u2, cs))));
251 }
252
253 Complex<long double> u(0.0L, 0.0L), rest(0.0L, 0.0L);
254 long double sgn = 1;
255
256 if (nz <= 1) {
257 u = -log(1.0L - z);
258 } else { // nz > 1
259 const long double arg = pz > 0.0 ? pz - PI : pz + PI;
260 const Complex<long double> lmz(lnz, arg); // log(-z)
261 const Complex<long double> lmz2 = lmz*lmz;
262 u = -log(1.0L - 1.0L/z);
263 rest = -31.0L*PI6/15120.0L
264 + lmz2*(-7.0L/720.0L*PI4 +
265 lmz2*(-1.0L/144.0L*PI2 - 1.0L/720.0L*lmz2));
266 sgn = -1;
267 }
268
269 return rest + sgn*u*horner(u, bf);
270}
271
272} // namespace flexiblesusy
Complex< T > horner(const Complex< T > &z, const T(&coeffs)[N]) noexcept
Definition: Li6.cpp:17
constexpr T norm(const Complex< T > &z) noexcept
Definition: complex.hpp:66
constexpr T arg(const Complex< T > &z) noexcept
Definition: complex.hpp:42
Complex< T > log(const Complex< T > &z) noexcept
Definition: complex.hpp:54
std::complex< double > Li6(const std::complex< double > &z_) noexcept
Complex polylogarithm .
Definition: Li6.cpp:42
double c0(double m1, double m2, double m3) noexcept
Definition: numerics.cpp:373
Class representing complex a number.
Definition: complex.hpp:34