flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
Li4.cpp
Go to the documentation of this file.
1// ====================================================================
2// This file is part of Polylogarithm.
3//
4// Polylogarithm is licenced under the GNU Lesser General Public
5// License (GNU LGPL) version 3.
6// ====================================================================
7
8#include "Li4.hpp"
9#include "complex.hpp"
10#include <cfloat>
11#include <cmath>
12
13namespace flexiblesusy {
14
15namespace {
16
17 template <typename T, int N>
18 Complex<T> horner(const Complex<T>& z, const T (&coeffs)[N]) noexcept
19 {
20 static_assert(N >= 2, "more than two coefficients required");
21
22 const T r = z.re + z.re;
23 const T s = z.re * z.re + z.im * z.im;
24 T a = coeffs[N - 1], b = coeffs[N - 2];
25
26 for (int i = N - 3; i >= 0; --i) {
27 const T t = a;
28 a = b + r * a;
29 b = coeffs[i] - s * t;
30 }
31
32 return Complex<T>(z.re*a + b, z.im*a);
33 }
34
36 double li4_neg(double x) noexcept
37 {
38 const double cp[] = {
39 0.9999999999999999952e+0, -1.8532099956062184217e+0,
40 1.1937642574034898249e+0, -3.1817912243893560382e-1,
41 3.2268284189261624841e-2, -8.3773570305913850724e-4
42 };
43 const double cq[] = {
44 1.0000000000000000000e+0, -1.9157099956062165688e+0,
45 1.3011504531166486419e+0, -3.7975653506939627186e-1,
46 4.5822723996558783670e-2, -1.8023912938765272341e-3,
47 1.0199621542882314929e-5
48 };
49
50 const double x2 = x*x;
51 const double x4 = x2*x2;
52 const double p = cp[0] + x*cp[1] + x2*(cp[2] + x*cp[3]) +
53 x4*(cp[4] + x*cp[5]);
54 const double q = cq[0] + x*cq[1] + x2*(cq[2] + x*cq[3]) +
55 x4*(cq[4] + x*cq[5] + x2*cq[6]);
56
57 return x*p/q;
58 }
59
61 double li4_half(double x) noexcept
62 {
63 const double cp[] = {
64 1.0000000000000000414e+0, -2.0588072418045364525e+0,
65 1.4713328756794826579e+0, -4.2608608613069811474e-1,
66 4.2975084278851543150e-2, -6.8314031819918920802e-4
67 };
68 const double cq[] = {
69 1.0000000000000000000e+0, -2.1213072418045207223e+0,
70 1.5915688992789175941e+0, -5.0327641401677265813e-1,
71 6.1467217495127095177e-2, -1.9061294280193280330e-3
72 };
73
74 const double x2 = x*x;
75 const double x4 = x2*x2;
76 const double p = cp[0] + x*cp[1] + x2*(cp[2] + x*cp[3]) +
77 x4*(cp[4] + x*cp[5]);
78 const double q = cq[0] + x*cq[1] + x2*(cq[2] + x*cq[3]) +
79 x4*(cq[4] + x*cq[5]);
80
81 return x*p/q;
82 }
83
85 double li4_mid(double x) noexcept
86 {
87 const double cp[] = {
88 3.2009826406098890447e-9, 9.9999994634837574160e-1,
89 -2.9144851228299341318e+0, 3.1891031447462342009e+0,
90 -1.6009125158511117090e+0, 3.5397747039432351193e-1,
91 -2.5230024124741454735e-2
92 };
93 const double cq[] = {
94 1.0000000000000000000e+0, -2.9769855248411488460e+0,
95 3.3628208295110572579e+0, -1.7782471949702788393e+0,
96 4.3364007973198649921e-1, -3.9535592340362510549e-2,
97 5.7373431535336755591e-4
98 };
99
100 const double x2 = x*x;
101 const double x4 = x2*x2;
102 const double p = cp[0] + x*cp[1] + x2*(cp[2] + x*cp[3]) +
103 x4*(cp[4] + x*cp[5] + x2*cp[6]);
104 const double q = cq[0] + x*cq[1] + x2*(cq[2] + x*cq[3]) +
105 x4*(cq[4] + x*cq[5] + x2*cq[6]);
106
107 return p/q;
108 }
109
111 double li4_one(double x) noexcept
112 {
113 const double zeta2 = 1.6449340668482264;
114 const double zeta3 = 1.2020569031595943;
115 const double zeta4 = 1.0823232337111382;
116 const double l = std::log(x);
117 const double l2 = l*l;
118
119 return zeta4 +
120 l*(zeta3 +
121 l*(0.5*zeta2 +
122 l*(11.0/36 - 1.0/6*std::log(-l) +
123 l*(-1.0/48 +
124 l*(-1.0/1440 +
125 l2*(1.0/604800 - 1.0/91445760*l2))))));
126 }
127
128} // anonymous namespace
129
136double Li4(double x) noexcept
137{
138 const double zeta2 = 1.6449340668482264;
139 const double zeta4 = 1.0823232337111382;
140
141 double app = 0, rest = 0, sgn = 1;
142
143 // transform x to [-1,1]
144 if (x < -1) {
145 const double l = std::log(-x);
146 const double l2 = l*l;
147 x = 1/x;
148 rest = -7.0/4*zeta4 + l2*(-0.5*zeta2 - 1.0/24*l2);
149 sgn = -1;
150 } else if (x == -1) {
151 return -7.0/8*zeta4;
152 } else if (x < 1) {
153 rest = 0;
154 sgn = 1;
155 } else if (x == 1) {
156 return zeta4;
157 } else { // x > 1
158 const double l = std::log(x);
159 const double l2 = l*l;
160 x = 1/x;
161 rest = 2*zeta4 + l2*(zeta2 - 1.0/24*l2);
162 sgn = -1;
163 }
164
165 if (x < 0) {
166 app = li4_neg(x);
167 } else if (x < 0.5) {
168 app = li4_half(x);
169 } else if (x < 0.8) {
170 app = li4_mid(x);
171 } else { // x <= 1
172 app = li4_one(x);
173 }
174
175 return rest + sgn*app;
176}
177
184std::complex<double> Li4(const std::complex<double>& z_) noexcept
185{
186 const double PI = 3.1415926535897932;
187 const double PI2 = PI*PI;
188 const double PI4 = PI2*PI2;
189 const double zeta4 = 1.0823232337111382;
190 const double bf[18] = {
191 1.0 , -7.0/16.0 ,
192 1.1651234567901235e-01, -1.9820601851851852e-02,
193 1.9279320987654321e-03, -3.1057098765432099e-05,
194 -1.5624009114857835e-05, 8.4851235467732066e-07,
195 2.2909616603189711e-07, -2.1832614218526917e-08,
196 -3.8828248791720156e-09, 5.4462921032203321e-10,
197 6.9608052106827254e-11, -1.3375737686445215e-11,
198 -1.2784852685266572e-12, 3.2605628580248922e-13,
199 2.3647571168618257e-14, -7.9231351220311617e-15
200 };
201
202 const Complex<double> z = { std::real(z_), std::imag(z_) };
203
204 if (z.im == 0) {
205 if (z.re <= 1) {
206 return Li4(z.re);
207 } else {
208 const double l = std::log(z.re);
209 return std::complex<double>(Li4(z.re), -1.0/6*PI*l*l*l);
210 }
211 }
212
213 const double nz = norm(z);
214 const double pz = arg(z);
215 const double lnz = std::log(nz);
216
217 if (lnz*lnz + pz*pz < 1) { // |log(z)| < 1
218 const Complex<double> u(lnz, pz); // log(z)
219 const Complex<double> u2 = u*u;
220 const double c1 = 1.2020569031595943; // zeta(3)
221 const double c2 = 0.82246703342411322;
222 const Complex<double> c3 = (11.0/6.0 - log(-u))/6.0;
223 const double c4 = -1.0/48.0;
224
225 const double cs[7] = {
226 -6.9444444444444444e-04, 1.6534391534391534e-06,
227 -1.0935444136502338e-08, 1.0438378493934049e-10,
228 -1.2165942300622435e-12, 1.6130006528350101e-14,
229 -2.3428810452879340e-16
230 };
231
232 return zeta4 + u2*(c2 + u2*c4) +
233 u*(c1 + u2*(c3 + u2*horner(u2, cs)));
234 }
235
236 Complex<double> u(0.0, 0.0), rest(0.0, 0.0);
237 double sgn = 1;
238
239 if (nz <= 1) {
240 u = -log(1.0 - z);
241 } else { // nz > 1
242 const double arg = pz > 0.0 ? pz - PI : pz + PI;
243 const Complex<double> lmz(lnz, arg); // log(-z)
244 const Complex<double> lmz2 = lmz*lmz;
245 u = -log(1.0 - 1.0/z);
246 rest = 1.0/360.0*(-7*PI4 + lmz2*(-30.0*PI2 - 15.0*lmz2));
247 sgn = -1;
248 }
249
250 const Complex<double> u2 = u*u;
251 const Complex<double> u4 = u2*u2;
252 const Complex<double> u8 = u4*u4;
253
254 return
255 rest + sgn * (
256 u*bf[0] +
257 u2*(bf[1] + u*bf[2]) +
258 u4*(bf[3] + u*bf[4] + u2*(bf[5] + u*bf[6])) +
259 u8*(bf[7] + u*bf[8] + u2*(bf[9] + u*bf[10]) +
260 u4*(bf[11] + u*bf[12] + u2*(bf[13] + u*bf[14]))) +
261 u8*u8*(bf[15] + u*bf[16] + u2*bf[17])
262 );
263}
264
271std::complex<long double> Li4(const std::complex<long double>& z_) noexcept
272{
273 const long double PI = 3.14159265358979323846264338327950288L;
274 const long double PI2 = PI*PI;
275 const long double PI4 = PI2*PI2;
276 const long double zeta4 = 1.08232323371113819151600369654116790L;
277 const long double bf[] = {
278 1.0L,
279 -7.0L/16.0L,
280 1.16512345679012345679012345679012346e-01L,
281 -1.98206018518518518518518518518518519e-02L,
282 1.92793209876543209876543209876543210e-03L,
283 -3.10570987654320987654320987654320988e-05L,
284 -1.56240091148578352983924736435264456e-05L,
285 8.48512354677320663715221538350790051e-07L,
286 2.29096166031897114453593835470042743e-07L,
287 -2.18326142185269169396153523137650122e-08L,
288 -3.88282487917201557228066203807765146e-09L,
289 5.44629210322033211825798588082320063e-10L,
290 6.96080521068272540787723341341208120e-11L,
291 -1.33757376864452151995780722036345205e-11L,
292 -1.27848526852665716041462463615741700e-12L,
293 3.26056285802489224287884181782170918e-13L,
294 2.36475711686182573623095048124390137e-14L,
295 -7.92313512203116170242999007113724954e-15L,
296 -4.34529157099841872504973716264753844e-16L,
297 1.92362700625359201161268755267526042e-16L,
298 7.81241433319595467072229389687370732e-18L,
299 -4.67180384480365552031762824287222012e-18L,
300#if LDBL_DIG > 18
301 -1.34353443298128478562602226758937243e-19L,
302 1.13568268513473432447646983759384846e-19L,
303 2.11527562024325868475059834141917946e-21L,
304 -2.76420263347465173882817292537310280e-21L,
305 -2.70681766082400642561090595581950049e-23L,
306 6.73720448286285721432671612656264303e-23L,
307 1.32872654566838229758180090450125398e-25L,
308 -1.64437730563678264678167631148886630e-24L,
309 8.28360589993393411098296734003488096e-27L,
310 4.01908484950693506997093150076214959e-26L,
311 -4.57571384448487903823597343465369976e-28L,
312 -9.83641090946151277583209749821167124e-28L,
313 1.69003395560378510677295231219028521e-29L,
314 2.41048055630598085046649041649017179e-29L,
315 -5.42661270567141825013250340589290005e-31L,
316 -5.91424295887417678643375999669283147e-31L,
317 1.62321109010873707727111761439681785e-32L,
318 1.45275954377402759461325873161579478e-32L,
319 -4.65389937002573704417216829815072974e-34L,
320 -3.57238626244413318154616242379067282e-34L,
321 1.29761714880310295825962542732877943e-35L,
322 8.79357407773938851103685229710271214e-36L,
323 -3.54800202048240308911663975982519909e-37L
324#endif
325 };
326
327 const Complex<long double> z = { std::real(z_), std::imag(z_) };
328
329 if (z.im == 0) {
330 if (z.re == 0) {
331 return 0.0L;
332 }
333 if (z.re == 1) {
334 return zeta4;
335 }
336 if (z.re == -1) {
337 return -7.0L*PI4/720.0L;
338 }
339 }
340
341 const long double nz = norm(z);
342 const long double pz = arg(z);
343 const long double lnz = std::log(nz);
344
345 if (lnz*lnz + pz*pz < 1) { // |log(z)| < 1
346 const Complex<long double> u(lnz, pz); // log(z)
347 const Complex<long double> u2 = u*u;
348 const long double c1 = 1.20205690315959428539973816151144999L; // zeta(3)
349 const long double c2 = 0.822467033424113218236207583323012595L;
350 const Complex<long double> c3 = (11.0L/6.0L - log(-u))/6.0L;
351 const long double c4 = -1.0L/48.0L;
352
353 const long double cs[] = {
354 -6.94444444444444444444444444444444444e-04L,
355 1.65343915343915343915343915343915344e-06L,
356 -1.09354441365023375605386187396769407e-08L,
357 1.04383784939340494896050451606007162e-10L,
358 -1.21659423006224353025699827046628393e-12L,
359 1.61300065283501012968488467709998678e-14L,
360 -2.34288104528793396933245465250860001e-16L,
361 3.64387716752943634635168923207929405e-18L,
362#if LDBL_DIG > 18
363 -5.97748681166655845456412242441216036e-20L,
364 1.02337130555150662198452683223504513e-21L,
365 -1.81455956138347480737900283560680332e-23L,
366 3.31302580384912709893344878064186841e-25L,
367 -6.20097932653619404041449128072466986e-27L,
368 1.18564508541733498204388623842798096e-28L,
369 -2.30933574895902885743620757867807721e-30L,
370 4.57154846962710278621075406449501719e-32L,
371 -9.18043553394696104844086650056356358e-34L,
372 1.86724930429686274238904009267803247e-35L,
373 -3.84151865355610606630482668147264051e-37L
374#endif
375 };
376
377 return zeta4 + u2*(c2 + u2*c4) +
378 u*(c1 + u2*(c3 + u2*horner(u2, cs)));
379 }
380
381 Complex<long double> u(0.0L, 0.0L), rest(0.0L, 0.0L);
382 long double sgn = 1;
383
384 if (nz <= 1) {
385 u = -log(1.0L - z);
386 } else { // nz > 1
387 const long double arg = pz > 0.0 ? pz - PI : pz + PI;
388 const Complex<long double> lmz(lnz, arg); // log(-z)
389 const Complex<long double> lmz2 = lmz*lmz;
390 u = -log(1.0L - 1.0L/z);
391 rest = 1.0L/360.0L*(-7*PI4 + lmz2*(-30.0L*PI2 - 15.0L*lmz2));
392 sgn = -1;
393 }
394
395 return rest + sgn*u*horner(u, bf);
396}
397
398} // namespace flexiblesusy
double li4_mid(double x) noexcept
Li_4(x) for x in [1/2,8/10].
Definition: Li4.cpp:85
double li4_half(double x) noexcept
Li_4(x) for x in [0,1/2].
Definition: Li4.cpp:61
double li4_neg(double x) noexcept
Li_4(x) for x in [-1,0].
Definition: Li4.cpp:36
double li4_one(double x) noexcept
Li_4(x) for x in [8/10,1].
Definition: Li4.cpp:111
Complex< T > horner(const Complex< T > &z, const T(&coeffs)[N]) noexcept
Definition: Li4.cpp:18
constexpr T norm(const Complex< T > &z) noexcept
Definition: complex.hpp:66
static constexpr double zeta2
Definition: wrappers.hpp:53
constexpr T arg(const Complex< T > &z) noexcept
Definition: complex.hpp:42
double Li4(double x) noexcept
Real 4-th order polylogarithm .
Definition: Li4.cpp:136
static constexpr double zeta4
Definition: wrappers.hpp:55
Complex< T > log(const Complex< T > &z) noexcept
Definition: complex.hpp:54
static constexpr double zeta3
Definition: wrappers.hpp:54
Class representing complex a number.
Definition: complex.hpp:34