Himalaya
Li2.f90
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 
8 !*********************************************************************
9 !> @brief Real dilogarithm \f$\mathrm{Li}_2(x)\f$
10 !> @param x real argument
11 !> @return \f$\mathrm{Li}_2(x)\f$
12 !> @author Alexander Voigt
13 !>
14 !> Implemented as an economized Pade approximation with a
15 !> maximum error of 4.16e-18.
16 !*********************************************************************
17 
18 double precision function dli2(x)
19  implicit none
20  double precision :: x, y, r, s, z, p, q, l, dhorner
21  double precision, parameter :: PI = 3.14159265358979324d0
22  double precision, parameter :: cp(8) = (/ &
23  1.0706105563309304277d+0, &
24  -4.5353562730201404017d+0, &
25  7.4819657596286408905d+0, &
26  -6.0516124315132409155d+0, &
27  2.4733515209909815443d+0, &
28  -4.6937565143754629578d-1, &
29  3.1608910440687221695d-2, &
30  -2.4630612614645039828d-4 /)
31  double precision, parameter :: cq(8) = (/ &
32  1.0000000000000000000d+0, &
33  -4.5355682121856044935d+0, &
34  8.1790029773247428573d+0, &
35  -7.4634190853767468810d+0, &
36  3.6245392503925290187d+0, &
37  -8.9936784740041174897d-1, &
38  9.8554565816757007266d-2, &
39  -3.2116618742475189569d-3 /)
40 
41  ! transform to [0, 1/2)
42  if (x .lt. -1) then
43  l = log(1 - x)
44  y = 1/(1 - x)
45  r = -pi**2/6 + l*(0.5d0*l - log(-x))
46  s = 1
47  elseif (x .eq. -1) then
48  dli2 = -pi**2/12
49  return
50  elseif (x .lt. 0) then
51  y = x/(x - 1)
52  r = -0.5d0*log(1 - x)**2
53  s = -1
54  elseif (x .eq. 0) then
55  dli2 = 0
56  return
57  elseif (x .lt. 0.5d0) then
58  y = x
59  r = 0
60  s = 1
61  elseif (x .lt. 1) then
62  y = 1 - x
63  r = pi**2/6 - log(x)*log(1 - x)
64  s = -1
65  elseif (x .eq. 1) then
66  dli2 = pi**2/6
67  return
68  elseif (x .lt. 2) then
69  l = log(x)
70  y = 1 - 1/x
71  r = pi**2/6 - l*(log(1 - 1/x) + 0.5d0*l)
72  s = 1
73  else
74  y = 1/x
75  r = pi**2/3 - 0.5d0*log(x)**2
76  s = -1
77  endif
78 
79  z = y - 0.25d0
80 
81  p = dhorner(z, cp, 8)
82  q = dhorner(z, cq, 8)
83 
84  dli2 = r + s*y*p/q
85 
86 end function dli2
87 
88 
89 !*********************************************************************
90 !> @brief Complex dilogarithm \f$\mathrm{Li}_2(z)\f$
91 !> @param z complex argument
92 !> @return \f$\mathrm{Li}_2(z)\f$
93 !> @note Implementation translated from SPheno by Alexander Voigt
94 !*********************************************************************
95 
96 double complex function cdli2(z)
97  implicit none
98  double complex :: z, rest, u, u2, u4, sum, fast_cdlog
99  double precision :: rz, iz, nz, sgn, dli2
100  double precision, parameter :: PI = 3.14159265358979324d0
101  double precision, parameter :: bf(10) = (/ &
102  - 1.0d0/4.0d0, &
103  + 1.0d0/36.0d0, &
104  - 1.0d0/3600.0d0, &
105  + 1.0d0/211680.0d0, &
106  - 1.0d0/10886400.0d0, &
107  + 1.0d0/526901760.0d0, &
108  - 4.0647616451442255d-11, &
109  + 8.9216910204564526d-13, &
110  - 1.9939295860721076d-14, &
111  + 4.5189800296199182d-16 /)
112 
113  rz = real(z)
114  iz = aimag(z)
115 
116  ! special cases
117  if (iz .eq. 0) then
118  if (rz .le. 1) cdli2 = dcmplx(dli2(rz), 0)
119  if (rz .gt. 1) cdli2 = dcmplx(dli2(rz), -pi*log(rz))
120  return
121  endif
122 
123  nz = rz**2 + iz**2
124 
125  if (nz .lt. epsilon(1d0)) then
126  cdli2 = z
127  return
128  endif
129 
130  ! transformation to |z| < 1, Re(z) <= 0.5
131  if (rz .le. 0.5d0) then
132  if (nz .gt. 1) then
133  u = -fast_cdlog(1 - 1/z)
134  rest = -0.5d0*fast_cdlog(-z)**2 - pi**2/6
135  sgn = -1
136  else ! nz <= 1
137  u = -fast_cdlog(1 - z)
138  rest = 0
139  sgn = 1
140  endif
141  else ! rz > 0.5D0
142  if (nz .le. 2*rz) then
143  u = -fast_cdlog(z)
144  rest = u*fast_cdlog(1 - z) + pi**2/6
145  sgn = -1
146  else ! nz > 2*rz
147  u = -fast_cdlog(1 - 1/z)
148  rest = -0.5d0*fast_cdlog(-z)**2 - pi**2/6
149  sgn = -1
150  endif
151  endif
152 
153  u2 = u**2
154  u4 = u2**2
155  sum = &
156  u + &
157  u2 * (bf(1) + &
158  u * (bf(2) + &
159  u2 * ( &
160  bf(3) + &
161  u2*bf(4) + &
162  u4*(bf(5) + u2*bf(6)) + &
163  u4*u4*(bf(7) + u2*bf(8) + u4*(bf(9) + u2*bf(10))) &
164  )))
165 
166  cdli2 = sgn*sum + rest
167 
168 end function cdli2
169 
170 
171 !*********************************************************************
172 !> @brief Evaluation of polynomial P(x) with len coefficients c
173 !> @param x real argument of P
174 !> @param c coefficients of P(x)
175 !> @param len number of coefficients
176 !> @return P(x)
177 !*********************************************************************
178 
179 double precision function dhorner(x, c, len)
180  implicit none
181  integer :: len, i
182  double precision :: x, c(len)
183 
184  dhorner = 0
185 
186  do i = len, 1, -1
187  dhorner = dhorner*x + c(i)
188  end do
189 
190 end function dhorner
191 
192 
193 !*********************************************************************
194 !> @brief Fast implementation of complex logarithm
195 !> @param z complex argument
196 !> @return log(z)
197 !*********************************************************************
198 double complex function fast_cdlog(z)
199  implicit none
200  double complex :: z
201  double precision :: re, im
202 
203  re = real(z)
204  im = aimag(z)
205  fast_cdlog = dcmplx(0.5d0*log(re**2 + im**2), datan2(im, re))
206 
207 end function fast_cdlog
208 
209 
210 !*********************************************************************
211 !> @brief C wrapper for complex dilogarithm
212 !> @param re_in real part of complex input
213 !> @param im_in imaginary part of complex input
214 !> @param re_out real part of complex output
215 !> @param im_out imagoutary part of complex output
216 !> @return log(z)
217 !*********************************************************************
218 subroutine li2c(re_in, im_in, re_out, im_out) bind(C, name="li2c_")
219  implicit none
220  double precision, intent(in) :: re_in, im_in
221  double precision, intent(out) :: re_out, im_out
222  double complex z, l, cdli2
223 
224  z = dcmplx(re_in, im_in)
225  l = cdli2(z)
226 
227  re_out = real(l)
228  im_out = aimag(l)
229 
230 end subroutine li2c
double precision function dli2(x)
Real dilogarithm .
Definition: Li2.f90:19
double precision function dhorner(x, c, len)
Evaluation of polynomial P(x) with len coefficients c.
Definition: Li2.f90:180
double complex function cdli2(z)
Complex dilogarithm .
Definition: Li2.f90:97
double complex function fast_cdlog(z)
Fast implementation of complex logarithm.
Definition: Li2.f90:199
subroutine li2c(re_in, im_in, re_out, im_out)
C wrapper for complex dilogarithm.
Definition: Li2.f90:219