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