flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
Li3.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 "Li3.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 li3_neg(double x) noexcept
32 {
33 const double cp[] = {
34 0.9999999999999999795e+0, -2.0281801754117129576e+0,
35 1.4364029887561718540e+0, -4.2240680435713030268e-1,
36 4.7296746450884096877e-2, -1.3453536579918419568e-3
37 };
38 const double cq[] = {
39 1.0000000000000000000e+0, -2.1531801754117049035e+0,
40 1.6685134736461140517e+0, -5.6684857464584544310e-1,
41 8.1999463370623961084e-2, -4.0756048502924149389e-3,
42 3.4316398489103212699e-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 li3_pos(double x) noexcept
57 {
58 const double cp[] = {
59 0.9999999999999999893e+0, -2.5224717303769789628e+0,
60 2.3204919140887894133e+0, -9.3980973288965037869e-1,
61 1.5728950200990509052e-1, -7.5485193983677071129e-3
62 };
63 const double cq[] = {
64 1.0000000000000000000e+0, -2.6474717303769836244e+0,
65 2.6143888433492184741e+0, -1.1841788297857667038e+0,
66 2.4184938524793651120e-1, -1.8220900115898156346e-2,
67 2.4927971540017376759e-4
68 };
69
70 const double x2 = x*x;
71 const double x4 = x2*x2;
72 const double p = cp[0] + x*cp[1] + x2*(cp[2] + x*cp[3]) +
73 x4*(cp[4] + x*cp[5]);
74 const double q = cq[0] + x*cq[1] + x2*(cq[2] + x*cq[3]) +
75 x4*(cq[4] + x*cq[5] + x2*cq[6]);
76
77 return x*p/q;
78 }
79
80} // anonymous namespace
81
88double Li3(double x) noexcept
89{
90 const double zeta2 = 1.6449340668482264;
91 const double zeta3 = 1.2020569031595943;
92
93 // transformation to [-1,0] and [0,1/2]
94 if (x < -1) {
95 const double l = std::log(-x);
96 return li3_neg(1/x) - l*(zeta2 + 1.0/6*l*l);
97 } else if (x == -1) {
98 return -0.75*zeta3;
99 } else if (x < 0) {
100 return li3_neg(x);
101 } else if (x == 0) {
102 return x;
103 } else if (x < 0.5) {
104 return li3_pos(x);
105 } else if (x == 0.5) {
106 return 0.53721319360804020;
107 } else if (x < 1) {
108 const double l = std::log(x);
109 return -li3_neg(1 - 1/x) - li3_pos(1 - x)
110 + zeta3 + l*(zeta2 + l*(-0.5*std::log1p(-x) + 1.0/6*l));
111 } else if (x == 1) {
112 return zeta3;
113 } else if (x < 2) {
114 const double l = std::log(x);
115 return -li3_neg(1 - x) - li3_pos(1 - 1/x)
116 + zeta3 + l*(zeta2 + l*(-0.5*std::log(x - 1) + 1.0/6*l));
117 } else { // x >= 2.0
118 const double l = std::log(x);
119 return li3_pos(1/x) + l*(2*zeta2 - 1.0/6*l*l);
120 }
121}
122
129std::complex<double> Li3(const std::complex<double>& z) noexcept
130{
131 const double PI = 3.1415926535897932;
132 const double zeta2 = 1.6449340668482264;
133 const double zeta3 = 1.2020569031595943;
134 const double bf[18] = {
135 1.0 , -3.0/8.0 ,
136 17.0/216.0 , -5.0/576.0 ,
137 1.2962962962962963e-04, 8.1018518518518519e-05,
138 -3.4193571608537595e-06, -1.3286564625850340e-06,
139 8.6608717561098513e-08, 2.5260875955320400e-08,
140 -2.1446944683640648e-09, -5.1401106220129789e-10,
141 5.2495821146008294e-11, 1.0887754406636318e-11,
142 -1.2779396094493695e-12, -2.3698241773087452e-13,
143 3.1043578879654623e-14, 5.2617586299125061e-15
144 };
145
146 const double rz = std::real(z);
147 const double iz = std::imag(z);
148
149 if (iz == 0) {
150 if (rz <= 1) {
151 return { Li3(rz), iz };
152 } else {
153 const double l = std::log(rz);
154 return { Li3(rz), -0.5*PI*l*l };
155 }
156 }
157
158 const double nz = std::abs(z);
159 const double pz = std::arg(z);
160 const double lnz = std::log(nz);
161
162 if (lnz*lnz + pz*pz < 1) { // |log(z)| < 1
163 const std::complex<double> u(lnz, pz); // log(z)
164 const auto u2 = u*u;
165 const auto u4 = u2*u2;
166 const auto u8 = u4*u4;
167 const auto c0 = zeta3 + u*(zeta2 - u2/12.0);
168 const auto c1 = 0.25 * (3.0 - 2.0*pos_log(-u));
169
170 const double cs[7] = {
171 -3.4722222222222222e-03, 1.1574074074074074e-05,
172 -9.8418997228521038e-08, 1.1482216343327454e-09,
173 -1.5815724990809166e-11, 2.4195009792525152e-13,
174 -3.9828977769894877e-15
175 };
176
177 return
178 c0 +
179 c1*u2 +
180 u4*(cs[0] + u2*cs[1]) +
181 u8*(cs[2] + u2*cs[3] + u4*(cs[4] + u2*cs[5])) +
182 u8*u8*cs[6];
183 }
184
185 std::complex<double> u(0.0, 0.0), rest(0.0, 0.0);
186
187 if (nz <= 1) {
188 u = -log1p(-z);
189 } else { // nz > 1
190 const double arg = pz > 0.0 ? pz - PI : pz + PI;
191 const std::complex<double> lmz(lnz, arg); // log(-z)
192 u = -log1p(-1.0/z);
193 rest = -lmz*(lmz*lmz/6.0 + zeta2);
194 }
195
196 const auto u2 = u*u;
197 const auto u4 = u2*u2;
198 const auto u8 = u4*u4;
199
200 return
201 rest +
202 u*bf[0] +
203 u2*(bf[1] + u*bf[2]) +
204 u4*(bf[3] + u*bf[4] + u2*(bf[5] + u*bf[6])) +
205 u8*(bf[7] + u*bf[8] + u2*(bf[9] + u*bf[10]) +
206 u4*(bf[11] + u*bf[12] + u2*(bf[13] + u*bf[14]))) +
207 u8*u8*(bf[15] + u*bf[16] + u2*bf[17]);
208}
209
216std::complex<long double> Li3(const std::complex<long double>& z) noexcept
217{
218 const long double PI = 3.14159265358979323846264338327950288L;
219 const long double zeta2 = 1.64493406684822643647241516664602519L;
220 const long double zeta3 = 1.20205690315959428539973816151144999L;
221 const long double bf[] = {
222 1.0L,
223 -3.0L/8.0L,
224 17.0L/216.0L,
225 -5.0L/576.0L,
226 7.0L/54000.0L,
227 7.0L/86400.0L,
228 -3.41935716085375949321527552820069827e-06L,
229 -1.32865646258503401360544217687074830e-06L,
230 8.66087175610985134794658604182413706e-08L,
231 2.52608759553203997648442092886537331e-08L,
232 -2.14469446836406476093388507573649032e-09L,
233 -5.14011062201297891533581769272004962e-10L,
234 5.24958211460082943639408880855807284e-11L,
235 1.08877544066363183753729715704249107e-11L,
236 -1.27793960944936953055818317540722120e-12L,
237 -2.36982417730874520997977788101244891e-13L,
238 3.10435788796546229428475327046556211e-14L,
239 5.26175862991250608413183925112250061e-15L,
240 -7.53847954994926536599250143226771028e-16L,
241 -1.18623225777522852530825009512459322e-16L,
242 1.83169799654913833820892731212815349e-17L,
243 2.70681710318373501514907347126169436e-18L,
244#if LDBL_DIG > 18
245 -4.45543389782963882643263099217632212e-19L,
246 -6.23754849225569465036532224739838641e-20L,
247 1.08515215348745349131365609968642833e-20L,
248 1.44911748660360819307349049665275324e-21L,
249 -2.64663397544589903347408911861443741e-22L,
250 -3.38976534885101047219258165860814078e-23L,
251 6.46404773360331088903253098219534234e-24L,
252 7.97583448960241242420922272590502795e-25L,
253 -1.58091787902874833559211176293826770e-25L,
254 -1.88614997296228681931102253988531956e-26L,
255 3.87155366384184733039971271888313319e-27L,
256 4.48011750023456073048653898320511684e-28L,
257 -9.49303387191183612641753676027699150e-29L,
258 -1.06828138090773812240182143033807908e-29L,
259 2.33044789361030518600785199019281371e-30L,
260 2.55607757265197540805635698286695865e-31L,
261 -5.72742160613725968447274458033057100e-32L,
262 -6.13471321379642358258549296897773326e-33L,
263 1.40908086040689448401268688489421700e-33L,
264 1.47642223976665341443182801167106626e-34L,
265 -3.47010516489959160555004020312910903e-35L,
266 -3.56210662409746357967357370318293608e-36L,
267 8.55369656823692105754731289124468101e-37L
268#endif
269 };
270
271 const long double rz = std::real(z);
272 const long double iz = std::imag(z);
273
274 if (iz == 0) {
275 if (rz == 0) {
276 return { rz, iz };
277 }
278 if (rz == 1) {
279 return { zeta3, iz };
280 }
281 if (rz == -1) {
282 return { -0.75L*zeta3, iz };
283 }
284 if (rz == 0.5L) {
285 return { 0.537213193608040200940623225594965827L, iz };
286 }
287 }
288
289 const long double nz = std::abs(z);
290 const long double pz = std::arg(z);
291 const long double lnz = std::log(nz);
292
293 if (lnz*lnz + pz*pz < 1) { // |log(z)| < 1
294 const std::complex<long double> u(lnz, pz); // log(z)
295 const auto u2 = u*u;
296 const auto c0 = zeta3 + u*(zeta2 - u2/12.0L);
297 const auto c1 = 0.25L * (3.0L - 2.0L*pos_log(-u));
298
299 const long double cs[] = {
300 -3.47222222222222222222222222222222222e-03L,
301 1.15740740740740740740740740740740741e-05L,
302 -9.84189972285210380448475686570924666e-08L,
303 1.14822163433274544385655496766607878e-09L,
304 -1.58157249908091658933409775160616911e-11L,
305 2.41950097925251519452732701564998016e-13L,
306 -3.98289777698948774786517290926462002e-15L,
307 6.92336661830592905806820954095065870e-17L,
308 -1.25527223044997727545846570912655367e-18L,
309#if LDBL_DIG > 18
310 2.35375400276846523056441171414060379e-20L,
311 -4.53639890345868701844750708901700830e-22L,
312 8.94516967039264316712031170773304472e-24L,
313 -1.79828400469549627172020247141015426e-25L,
314 3.67549976479373844433604733912674099e-27L,
315 -7.62080797156479522953948500963765478e-29L,
316 1.60004196436948597517376392257325602e-30L,
317 -3.39676114756037558792312060520851852e-32L,
318 7.28227228675776469531725636144432664e-34L,
319 -1.57502264795800348718497893940378261e-35L,
320 3.43354009248058933588797212016527038e-37L
321#endif
322 };
323
324 return c0 + u2*(c1 + u2*horner<0>(u2, cs));
325 }
326
327 std::complex<long double> u(0.0L, 0.0L), rest(0.0L, 0.0L);
328
329 if (nz <= 1) {
330 u = -log1p(-z);
331 } else { // nz > 1
332 const long double arg = pz > 0.0 ? pz - PI : pz + PI;
333 const std::complex<long double> lmz(lnz, arg); // log(-z)
334 u = -log1p(-1.0L/z);
335 rest = -lmz*(lmz*lmz/6.0L + zeta2);
336 }
337
338 return rest + u*horner<0>(u, bf);
339}
340
341} // namespace flexiblesusy
double li3_neg(double x) noexcept
Li_3(x) for x in [-1,0].
Definition Li3.cpp:31
double li3_pos(double x) noexcept
Li_3(x) for x in [0,1/2].
Definition Li3.cpp:56
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 Li3(double x) noexcept
Real trilogarithm .
Definition Li3.cpp:88
static constexpr double zeta3
Definition wrappers.hpp:55