flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
Li2.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 "Li2.hpp"
20#include "horner.hpp"
21#include "log.hpp"
22#include <cfloat>
23#include <cmath>
24#include <complex>
25#include <limits>
26
27namespace flexiblesusy {
28
38float Li2(float x) noexcept
39{
40 const float PI = 3.14159265f;
41 const float P[] = { 1.00000020f, -0.780790946f, 0.0648256871f };
42 const float Q[] = { 1.00000000f, -1.03077545f, 0.211216710f };
43
44 float y = 0, r = 0, s = 1;
45
46 // transform to [0, 1/2]
47 if (x < -1) {
48 const float l = std::log(1 - x);
49 y = 1/(1 - x);
50 r = -PI*PI/6 + l*(0.5f*l - std::log(-x));
51 s = 1;
52 } else if (x == -1) {
53 return -PI*PI/12;
54 } else if (x < 0) {
55 const float l = std::log1p(-x);
56 y = x/(x - 1);
57 r = -0.5f*l*l;
58 s = -1;
59 } else if (x == 0) {
60 return x;
61 } else if (x < 0.5f) {
62 y = x;
63 r = 0;
64 s = 1;
65 } else if (x < 1) {
66 y = 1 - x;
67 r = PI*PI/6 - std::log(x)*std::log1p(-x);
68 s = -1;
69 } else if (x == 1) {
70 return PI*PI/6;
71 } else if (x < 2) {
72 const float l = std::log(x);
73 y = 1 - 1/x;
74 r = PI*PI/6 - l*(std::log(y) + 0.5f*l);
75 s = 1;
76 } else {
77 const float l = std::log(x);
78 y = 1/x;
79 r = PI*PI/3 - 0.5f*l*l;
80 s = -1;
81 }
82
83 const float y2 = y*y;
84 const float p = P[0] + y * P[1] + y2 * P[2];
85 const float q = Q[0] + y * Q[1] + y2 * Q[2];
86
87 return r + s*y*p/q;
88}
89
100double Li2(double x) noexcept
101{
102 const double PI = 3.1415926535897932;
103 const double P[] = {
104 0.9999999999999999502e+0,
105 -2.6883926818565423430e+0,
106 2.6477222699473109692e+0,
107 -1.1538559607887416355e+0,
108 2.0886077795020607837e-1,
109 -1.0859777134152463084e-2
110 };
111 const double Q[] = {
112 1.0000000000000000000e+0,
113 -2.9383926818565635485e+0,
114 3.2712093293018635389e+0,
115 -1.7076702173954289421e+0,
116 4.1596017228400603836e-1,
117 -3.9801343754084482956e-2,
118 8.2743668974466659035e-4
119 };
120
121 double y = 0, r = 0, s = 1;
122
123 // transform to [0, 1/2]
124 if (x < -1) {
125 const double l = std::log(1 - x);
126 y = 1/(1 - x);
127 r = -PI*PI/6 + l*(0.5*l - std::log(-x));
128 s = 1;
129 } else if (x == -1) {
130 return -PI*PI/12;
131 } else if (x < 0) {
132 const double l = std::log1p(-x);
133 y = x/(x - 1);
134 r = -0.5*l*l;
135 s = -1;
136 } else if (x == 0) {
137 return x;
138 } else if (x < 0.5) {
139 y = x;
140 r = 0;
141 s = 1;
142 } else if (x < 1) {
143 y = 1 - x;
144 r = PI*PI/6 - std::log(x)*std::log1p(-x);
145 s = -1;
146 } else if (x == 1) {
147 return PI*PI/6;
148 } else if (x < 2) {
149 const double l = std::log(x);
150 y = 1 - 1/x;
151 r = PI*PI/6 - l*(std::log(y) + 0.5*l);
152 s = 1;
153 } else {
154 const double l = std::log(x);
155 y = 1/x;
156 r = PI*PI/3 - 0.5*l*l;
157 s = -1;
158 }
159
160 const double y2 = y*y;
161 const double y4 = y2*y2;
162 const double p = P[0] + y * P[1] + y2 * (P[2] + y * P[3]) +
163 y4 * (P[4] + y * P[5]);
164 const double q = Q[0] + y * Q[1] + y2 * (Q[2] + y * Q[3]) +
165 y4 * (Q[4] + y * Q[5] + y2 * Q[6]);
166
167 return r + s*y*p/q;
168}
169
180long double Li2(long double x) noexcept
181{
182 const long double PI = 3.14159265358979323846264338327950288L;
183
184#if LDBL_DIG <= 18
185 const long double P[] = {
186 1.07061055633093042767673531395124630e+0L,
187 -5.25056559620492749887983310693176896e+0L,
188 1.03934845791141763662532570563508185e+1L,
189 -1.06275187429164237285280053453630651e+1L,
190 5.95754800847361224707276004888482457e+0L,
191 -1.78704147549824083632603474038547305e+0L,
192 2.56952343145676978700222949739349644e-1L,
193 -1.33237248124034497789318026957526440e-2L,
194 7.91217309833196694976662068263629735e-5L
195 };
196 const long double Q[] = {
197 1.00000000000000000000000000000000000e+0L,
198 -5.20360694854541370154051736496901638e+0L,
199 1.10984640257222420881180161591516337e+1L,
200 -1.24997590867514516374467903875677930e+1L,
201 7.97919868560471967115958363930214958e+0L,
202 -2.87732383715218390800075864637472768e+0L,
203 5.49210416881086355164851972523370137e-1L,
204 -4.73366369162599860878254400521224717e-2L,
205 1.23136575793833628711851523557950417e-3L
206 };
207#else
208 const long double P[] = {
209 1.0706105563309304276767353139512463033e+0L,
210 -1.0976999936495889694316759019749736514e+1L,
211 5.0926847456521671435598196295391041399e+1L,
212 -1.4137651316583179225403308056234710093e+2L,
213 2.6167438966024905838946321639772104746e+2L,
214 -3.4058684964478756354428571563597134889e+2L,
215 3.2038320769322335817541819891481680235e+2L,
216 -2.2042602382067574460998180123431383994e+2L,
217 1.1098617775200190748144566197068215051e+2L,
218 -4.0511655788875306581280201485439376229e+1L,
219 1.0505482055068989911823839054507173824e+1L,
220 -1.8711701614474515075977773430379529915e+0L,
221 2.1700009060344649725726270289240541652e-1L,
222 -1.5030137964245010798524220531488795883e-2L,
223 5.3441650657913964794668981233490297624e-4L,
224 -7.0813883289232115572593407126124042503e-6L,
225 9.9037749983459843207756017329825486520e-9L
226 };
227 const long double Q[] = {
228 1.0000000000000000000000000000000000000e+0L,
229 -1.0552362671556327276432317611336360654e+1L,
230 5.0559576537049301822461383847757604795e+1L,
231 -1.4554341156550484644439941130107249144e+2L,
232 2.8070530313005385434963768448877956414e+2L,
233 -3.8295927403204227055447294669165437162e+2L,
234 3.8034123327297619837621395664129395552e+2L,
235 -2.7878320883603471098333035075019703189e+2L,
236 1.5127204204944666467295435798726892255e+2L,
237 -6.0401294167088266781532200159750431265e+1L,
238 1.7480717870136655299932069333598290551e+1L,
239 -3.5731199220918363429317367913920234597e+0L,
240 4.9537900060585746351429453828993042241e-1L,
241 -4.3750415383481013167382471956794084257e-2L,
242 2.2234568413141078158637017098109483650e-3L,
243 -5.4149527323164210917629185927908003034e-5L,
244 4.1629116823949062782848730828350635143e-7L
245 };
246#endif
247
248 long double y = 0, r = 0, s = 1;
249
250 // transform to [0, 1/2)
251 if (x < -1) {
252 const long double l = std::log(1 - x);
253 y = 1/(1 - x);
254 r = -PI*PI/6 + l*(0.5L*l - std::log(-x));
255 s = 1;
256 } else if (x == -1) {
257 return -PI*PI/12;
258 } else if (x < 0) {
259 const long double l = std::log1p(-x);
260 y = x/(x - 1);
261 r = -0.5L*l*l;
262 s = -1;
263 } else if (x == 0) {
264 return x;
265 } else if (x < 0.5L) {
266 y = x;
267 r = 0;
268 s = 1;
269 } else if (x < 1) {
270 y = 1 - x;
271 r = PI*PI/6 - std::log(x)*std::log1p(-x);
272 s = -1;
273 } else if (x == 1) {
274 return PI*PI/6;
275 } else if (x < 2) {
276 const long double l = std::log(x);
277 y = 1 - 1/x;
278 r = PI*PI/6 - l*(std::log(y) + 0.5L*l);
279 s = 1;
280 } else {
281 const long double l = std::log(x);
282 y = 1/x;
283 r = PI*PI/3 - 0.5L*l*l;
284 s = -1;
285 }
286
287 const long double z = y - 0.25L;
288
289 const long double p = horner(z, P);
290 const long double q = horner(z, Q);
291
292 return r + s*y*p/q;
293}
294
303std::complex<float> Li2(const std::complex<float>& z) noexcept
304{
305 const float PI = 3.14159265f;
306
307 // bf[1..N-1] are the even Bernoulli numbers / (2 n + 1)!
308 const float bf[] = {
309 - 1.0f/4,
310 + 1.0f/36,
311 - 1.0f/3600,
312 + 1.0f/211680
313 };
314
315 const float rz = std::real(z);
316 const float iz = std::imag(z);
317
318 // special cases
319 if (iz == 0) {
320 if (rz <= 1) {
321 return { Li2(rz), iz };
322 }
323 // rz > 1
324 return { Li2(rz), -PI*std::log(rz) };
325 }
326
327 const float nz = std::norm(z);
328
329 if (nz < std::numeric_limits<float>::epsilon()) {
330 return z*(1.0f + 0.25f*z);
331 }
332
333 std::complex<float> u(0.0f, 0.0f), rest(0.0f, 0.0f);
334 float sgn = 1;
335
336 // transformation to |z|<1, Re(z)<=0.5
337 if (rz <= 0.5f) {
338 if (nz > 1) {
339 const auto lz = std::log(-z);
340 u = -log1p(-1.0f/z);
341 rest = -0.5f*lz*lz - PI*PI/6;
342 sgn = -1;
343 } else { // nz <= 1
344 u = -log1p(-z);
345 rest = 0;
346 sgn = 1;
347 }
348 } else { // rz > 0.5
349 if (nz <= 2*rz) {
350 u = -std::log(z);
351 rest = u*log1p(-z) + PI*PI/6;
352 sgn = -1;
353 } else { // nz > 2*rz
354 const auto lz = std::log(-z);
355 u = -log1p(-1.0f/z);
356 rest = -0.5f*lz*lz - PI*PI/6;
357 sgn = -1;
358 }
359 }
360
361 const auto u2(u*u);
362
363 return sgn*(u + u2*(bf[0] + u*horner<1>(u2, bf))) + rest;
364}
365
366
375std::complex<double> Li2(const std::complex<double>& z) noexcept
376{
377 const double PI = 3.1415926535897932;
378
379 // bf[1..N-1] are the even Bernoulli numbers / (2 n + 1)!
380 // generated by: Table[BernoulliB[2 n]/(2 n + 1)!, {n, 1, 9}]
381 const double bf[10] = {
382 - 1.0/4.0,
383 + 1.0/36.0,
384 - 1.0/3600.0,
385 + 1.0/211680.0,
386 - 1.0/10886400.0,
387 + 1.0/526901760.0,
388 - 4.0647616451442255e-11,
389 + 8.9216910204564526e-13,
390 - 1.9939295860721076e-14,
391 + 4.5189800296199182e-16
392 };
393
394 const double rz = std::real(z);
395 const double iz = std::imag(z);
396
397 // special cases
398 if (iz == 0) {
399 if (rz <= 1) {
400 return { Li2(rz), iz };
401 }
402 // rz > 1
403 return { Li2(rz), -PI*std::log(rz) };
404 }
405
406 const double nz = std::norm(z);
407
408 if (nz < std::numeric_limits<double>::epsilon()) {
409 return z*(1.0 + 0.25*z);
410 }
411
412 std::complex<double> u(0.0, 0.0), rest(0.0, 0.0);
413 double sgn = 1;
414
415 // transformation to |z|<1, Re(z)<=0.5
416 if (rz <= 0.5) {
417 if (nz > 1) {
418 const auto lz = std::log(-z);
419 u = -log1p(-1.0/z);
420 rest = -0.5*lz*lz - PI*PI/6;
421 sgn = -1;
422 } else { // nz <= 1
423 u = -log1p(-z);
424 rest = 0;
425 sgn = 1;
426 }
427 } else { // rz > 0.5
428 if (nz <= 2*rz) {
429 u = -std::log(z);
430 rest = u*log1p(-z) + PI*PI/6;
431 sgn = -1;
432 } else { // nz > 2*rz
433 const auto lz = std::log(-z);
434 u = -log1p(-1.0/z);
435 rest = -0.5*lz*lz - PI*PI/6;
436 sgn = -1;
437 }
438 }
439
440 const auto u2(u*u);
441
442 return sgn*(u + u2*(bf[0] + u*horner<1>(u2, bf))) + rest;
443}
444
453std::complex<long double> Li2(const std::complex<long double>& z) noexcept
454{
455 const long double PI = 3.14159265358979323846264338327950288L;
456
457 // bf[1..N-1] are the even Bernoulli numbers / (2 n + 1)!
458 // generated by: Table[BernoulliB[2 n]/(2 n + 1)!, {n, 1, 22}]
459 const long double bf[] = {
460 -1.0L/4.0L ,
461 1.0L/36.0L ,
462 -1.0L/3600.0L ,
463 1.0L/211680.0L ,
464 -1.0L/10886400.0L ,
465 1.0L/526901760.0L ,
466 -4.06476164514422552680590938629196667e-11L,
467 8.92169102045645255521798731675274885e-13L,
468 -1.99392958607210756872364434779378971e-14L,
469 4.51898002961991819165047655285559323e-16L,
470 -1.03565176121812470144834115422186567e-17L,
471#if LDBL_DIG > 18
472 2.39521862102618674574028374300098038e-19L,
473 -5.58178587432500933628307450562541991e-21L,
474 1.30915075541832128581230739918659230e-22L,
475 -3.08741980242674029324227976486646243e-24L,
476 7.31597565270220342035790560925214859e-26L,
477 -1.74084565723400074098905514775970255e-27L,
478 4.15763564461389971961789962077522667e-29L,
479 -9.96214848828462210319400670245583885e-31L,
480 2.39403442489616530052116798789374956e-32L,
481 -5.76834735536739008429179316187765424e-34L,
482 1.39317947964700797782788660391154833e-35L,
483 -3.37212196548508947046847363525493096e-37L
484#endif
485 };
486
487 const long double rz = std::real(z);
488 const long double iz = std::imag(z);
489
490 // special cases
491 if (iz == 0) {
492 if (rz <= 1) {
493 return { Li2(rz), iz };
494 }
495 // rz > 1
496 return { Li2(rz), -PI*std::log(rz) };
497 }
498
499 const long double nz = std::norm(z);
500
501 if (nz < std::numeric_limits<long double>::epsilon()) {
502 return z*(1.0L + 0.25L*z);
503 }
504
505 std::complex<long double> u(0.0L, 0.0L), rest(0.0L, 0.0L);
506 long double sgn = 1;
507
508 // transformation to |z|<1, Re(z)<=0.5
509 if (rz <= 0.5L) {
510 if (nz > 1) {
511 const auto lz = std::log(-z);
512 u = -log1p(-1.0L/z);
513 rest = -0.5L*lz*lz - PI*PI/6;
514 sgn = -1;
515 } else { // nz <= 1
516 u = -log1p(-z);
517 rest = 0;
518 sgn = 1;
519 }
520 } else { // rz > 0.5L
521 if (nz <= 2*rz) {
522 u = -std::log(z);
523 rest = u*log1p(-z) + PI*PI/6;
524 sgn = -1;
525 } else { // nz > 2*rz
526 const auto lz = std::log(-z);
527 u = -log1p(-1.0L/z);
528 rest = -0.5L*lz*lz - PI*PI/6;
529 sgn = -1;
530 }
531 }
532
533 const auto u2(u*u);
534
535 return sgn*(u + u2*(bf[0] + u*horner<1>(u2, bf))) + rest;
536}
537
538} // namespace flexiblesusy
#define P(i)
Definition defs.h:630
T horner(T x, const T(&c)[N]) noexcept
Definition horner.hpp:27
std::complex< T > log1p(const std::complex< T > &z) noexcept
returns log(1 + z) for complex z
Definition log.hpp:30
float Li2(float x) noexcept
Real dilogarithm .
Definition Li2.cpp:38