gsl_specfunc__dilog.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. /* specfunc/dilog.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004 Gerard Jungman
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. /* Author: G. Jungman */
  20. #include "gsl__config.h"
  21. #include "gsl_math.h"
  22. #include "gsl_errno.h"
  23. #include "gsl_sf_clausen.h"
  24. #include "gsl_sf_trig.h"
  25. #include "gsl_sf_log.h"
  26. #include "gsl_sf_dilog.h"
  27. /* Evaluate series for real dilog(x)
  28. * Sum[ x^k / k^2, {k,1,Infinity}]
  29. *
  30. * Converges rapidly for |x| < 1/2.
  31. */
  32. static
  33. int
  34. dilog_series_1(const double x, gsl_sf_result * result)
  35. {
  36. const int kmax = 1000;
  37. double sum = x;
  38. double term = x;
  39. int k;
  40. for(k=2; k<kmax; k++) {
  41. const double rk = (k-1.0)/k;
  42. term *= x;
  43. term *= rk*rk;
  44. sum += term;
  45. if(fabs(term/sum) < GSL_DBL_EPSILON) break;
  46. }
  47. result->val = sum;
  48. result->err = 2.0 * fabs(term);
  49. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  50. if(k == kmax)
  51. GSL_ERROR ("error", GSL_EMAXITER);
  52. else
  53. return GSL_SUCCESS;
  54. }
  55. /* Compute the associated series
  56. *
  57. * sum_{k=1}{infty} r^k / (k^2 (k+1))
  58. *
  59. * This is a series which appears in the one-step accelerated
  60. * method, which splits out one elementary function from the
  61. * full definition of Li_2(x). See below.
  62. */
  63. static int
  64. series_2(double r, gsl_sf_result * result)
  65. {
  66. static const int kmax = 100;
  67. double rk = r;
  68. double sum = 0.5 * r;
  69. int k;
  70. for(k=2; k<10; k++)
  71. {
  72. double ds;
  73. rk *= r;
  74. ds = rk/(k*k*(k+1.0));
  75. sum += ds;
  76. }
  77. for(; k<kmax; k++)
  78. {
  79. double ds;
  80. rk *= r;
  81. ds = rk/(k*k*(k+1.0));
  82. sum += ds;
  83. if(fabs(ds/sum) < 0.5*GSL_DBL_EPSILON) break;
  84. }
  85. result->val = sum;
  86. result->err = 2.0 * kmax * GSL_DBL_EPSILON * fabs(sum);
  87. return GSL_SUCCESS;
  88. }
  89. /* Compute Li_2(x) using the accelerated series representation.
  90. *
  91. * Li_2(x) = 1 + (1-x)ln(1-x)/x + series_2(x)
  92. *
  93. * assumes: -1 < x < 1
  94. */
  95. static int
  96. dilog_series_2(double x, gsl_sf_result * result)
  97. {
  98. const int stat_s3 = series_2(x, result);
  99. double t;
  100. if(x > 0.01)
  101. t = (1.0 - x) * log(1.0-x) / x;
  102. else
  103. {
  104. static const double c3 = 1.0/3.0;
  105. static const double c4 = 1.0/4.0;
  106. static const double c5 = 1.0/5.0;
  107. static const double c6 = 1.0/6.0;
  108. static const double c7 = 1.0/7.0;
  109. static const double c8 = 1.0/8.0;
  110. const double t68 = c6 + x*(c7 + x*c8);
  111. const double t38 = c3 + x *(c4 + x *(c5 + x * t68));
  112. t = (x - 1.0) * (1.0 + x*(0.5 + x*t38));
  113. }
  114. result->val += 1.0 + t;
  115. result->err += 2.0 * GSL_DBL_EPSILON * fabs(t);
  116. return stat_s3;
  117. }
  118. /* Calculates Li_2(x) for real x. Assumes x >= 0.0.
  119. */
  120. static
  121. int
  122. dilog_xge0(const double x, gsl_sf_result * result)
  123. {
  124. if(x > 2.0) {
  125. gsl_sf_result ser;
  126. const int stat_ser = dilog_series_2(1.0/x, &ser);
  127. const double log_x = log(x);
  128. const double t1 = M_PI*M_PI/3.0;
  129. const double t2 = ser.val;
  130. const double t3 = 0.5*log_x*log_x;
  131. result->val = t1 - t2 - t3;
  132. result->err = GSL_DBL_EPSILON * fabs(log_x) + ser.err;
  133. result->err += GSL_DBL_EPSILON * (fabs(t1) + fabs(t2) + fabs(t3));
  134. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  135. return stat_ser;
  136. }
  137. else if(x > 1.01) {
  138. gsl_sf_result ser;
  139. const int stat_ser = dilog_series_2(1.0 - 1.0/x, &ser);
  140. const double log_x = log(x);
  141. const double log_term = log_x * (log(1.0-1.0/x) + 0.5*log_x);
  142. const double t1 = M_PI*M_PI/6.0;
  143. const double t2 = ser.val;
  144. const double t3 = log_term;
  145. result->val = t1 + t2 - t3;
  146. result->err = GSL_DBL_EPSILON * fabs(log_x) + ser.err;
  147. result->err += GSL_DBL_EPSILON * (fabs(t1) + fabs(t2) + fabs(t3));
  148. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  149. return stat_ser;
  150. }
  151. else if(x > 1.0) {
  152. /* series around x = 1.0 */
  153. const double eps = x - 1.0;
  154. const double lne = log(eps);
  155. const double c0 = M_PI*M_PI/6.0;
  156. const double c1 = 1.0 - lne;
  157. const double c2 = -(1.0 - 2.0*lne)/4.0;
  158. const double c3 = (1.0 - 3.0*lne)/9.0;
  159. const double c4 = -(1.0 - 4.0*lne)/16.0;
  160. const double c5 = (1.0 - 5.0*lne)/25.0;
  161. const double c6 = -(1.0 - 6.0*lne)/36.0;
  162. const double c7 = (1.0 - 7.0*lne)/49.0;
  163. const double c8 = -(1.0 - 8.0*lne)/64.0;
  164. result->val = c0+eps*(c1+eps*(c2+eps*(c3+eps*(c4+eps*(c5+eps*(c6+eps*(c7+eps*c8)))))));
  165. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  166. return GSL_SUCCESS;
  167. }
  168. else if(x == 1.0) {
  169. result->val = M_PI*M_PI/6.0;
  170. result->err = 2.0 * GSL_DBL_EPSILON * M_PI*M_PI/6.0;
  171. return GSL_SUCCESS;
  172. }
  173. else if(x > 0.5) {
  174. gsl_sf_result ser;
  175. const int stat_ser = dilog_series_2(1.0-x, &ser);
  176. const double log_x = log(x);
  177. const double t1 = M_PI*M_PI/6.0;
  178. const double t2 = ser.val;
  179. const double t3 = log_x*log(1.0-x);
  180. result->val = t1 - t2 - t3;
  181. result->err = GSL_DBL_EPSILON * fabs(log_x) + ser.err;
  182. result->err += GSL_DBL_EPSILON * (fabs(t1) + fabs(t2) + fabs(t3));
  183. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  184. return stat_ser;
  185. }
  186. else if(x > 0.25) {
  187. return dilog_series_2(x, result);
  188. }
  189. else if(x > 0.0) {
  190. return dilog_series_1(x, result);
  191. }
  192. else {
  193. /* x == 0.0 */
  194. result->val = 0.0;
  195. result->err = 0.0;
  196. return GSL_SUCCESS;
  197. }
  198. }
  199. /* Evaluate the series representation for Li2(z):
  200. *
  201. * Li2(z) = Sum[ |z|^k / k^2 Exp[i k arg(z)], {k,1,Infinity}]
  202. * |z| = r
  203. * arg(z) = theta
  204. *
  205. * Assumes 0 < r < 1.
  206. * It is used only for small r.
  207. */
  208. static
  209. int
  210. dilogc_series_1(
  211. const double r,
  212. const double x,
  213. const double y,
  214. gsl_sf_result * real_result,
  215. gsl_sf_result * imag_result
  216. )
  217. {
  218. const double cos_theta = x/r;
  219. const double sin_theta = y/r;
  220. const double alpha = 1.0 - cos_theta;
  221. const double beta = sin_theta;
  222. double ck = cos_theta;
  223. double sk = sin_theta;
  224. double rk = r;
  225. double real_sum = r*ck;
  226. double imag_sum = r*sk;
  227. const int kmax = 50 + (int)(22.0/(-log(r))); /* tuned for double-precision */
  228. int k;
  229. for(k=2; k<kmax; k++) {
  230. double dr, di;
  231. double ck_tmp = ck;
  232. ck = ck - (alpha*ck + beta*sk);
  233. sk = sk - (alpha*sk - beta*ck_tmp);
  234. rk *= r;
  235. dr = rk/((double)k*k) * ck;
  236. di = rk/((double)k*k) * sk;
  237. real_sum += dr;
  238. imag_sum += di;
  239. if(fabs((dr*dr + di*di)/(real_sum*real_sum + imag_sum*imag_sum)) < GSL_DBL_EPSILON*GSL_DBL_EPSILON) break;
  240. }
  241. real_result->val = real_sum;
  242. real_result->err = 2.0 * kmax * GSL_DBL_EPSILON * fabs(real_sum);
  243. imag_result->val = imag_sum;
  244. imag_result->err = 2.0 * kmax * GSL_DBL_EPSILON * fabs(imag_sum);
  245. return GSL_SUCCESS;
  246. }
  247. /* Compute
  248. *
  249. * sum_{k=1}{infty} z^k / (k^2 (k+1))
  250. *
  251. * This is a series which appears in the one-step accelerated
  252. * method, which splits out one elementary function from the
  253. * full definition of Li_2.
  254. */
  255. static int
  256. series_2_c(
  257. double r,
  258. double x,
  259. double y,
  260. gsl_sf_result * sum_re,
  261. gsl_sf_result * sum_im
  262. )
  263. {
  264. const double cos_theta = x/r;
  265. const double sin_theta = y/r;
  266. const double alpha = 1.0 - cos_theta;
  267. const double beta = sin_theta;
  268. double ck = cos_theta;
  269. double sk = sin_theta;
  270. double rk = r;
  271. double real_sum = 0.5 * r*ck;
  272. double imag_sum = 0.5 * r*sk;
  273. const int kmax = 30 + (int)(18.0/(-log(r))); /* tuned for double-precision */
  274. int k;
  275. for(k=2; k<kmax; k++)
  276. {
  277. double dr, di;
  278. const double ck_tmp = ck;
  279. ck = ck - (alpha*ck + beta*sk);
  280. sk = sk - (alpha*sk - beta*ck_tmp);
  281. rk *= r;
  282. dr = rk/((double)k*k*(k+1.0)) * ck;
  283. di = rk/((double)k*k*(k+1.0)) * sk;
  284. real_sum += dr;
  285. imag_sum += di;
  286. if(fabs((dr*dr + di*di)/(real_sum*real_sum + imag_sum*imag_sum)) < GSL_DBL_EPSILON*GSL_DBL_EPSILON) break;
  287. }
  288. sum_re->val = real_sum;
  289. sum_re->err = 2.0 * kmax * GSL_DBL_EPSILON * fabs(real_sum);
  290. sum_im->val = imag_sum;
  291. sum_im->err = 2.0 * kmax * GSL_DBL_EPSILON * fabs(imag_sum);
  292. return GSL_SUCCESS;
  293. }
  294. /* Compute Li_2(z) using the one-step accelerated series.
  295. *
  296. * Li_2(z) = 1 + (1-z)ln(1-z)/z + series_2_c(z)
  297. *
  298. * z = r exp(i theta)
  299. * assumes: r < 1
  300. * assumes: r > epsilon, so that we take no special care with log(1-z)
  301. */
  302. static
  303. int
  304. dilogc_series_2(
  305. const double r,
  306. const double x,
  307. const double y,
  308. gsl_sf_result * real_dl,
  309. gsl_sf_result * imag_dl
  310. )
  311. {
  312. if(r == 0.0)
  313. {
  314. real_dl->val = 0.0;
  315. imag_dl->val = 0.0;
  316. real_dl->err = 0.0;
  317. imag_dl->err = 0.0;
  318. return GSL_SUCCESS;
  319. }
  320. else
  321. {
  322. gsl_sf_result sum_re;
  323. gsl_sf_result sum_im;
  324. const int stat_s3 = series_2_c(r, x, y, &sum_re, &sum_im);
  325. /* t = ln(1-z)/z */
  326. gsl_sf_result ln_omz_r;
  327. gsl_sf_result ln_omz_theta;
  328. const int stat_log = gsl_sf_complex_log_e(1.0-x, -y, &ln_omz_r, &ln_omz_theta);
  329. const double t_x = ( ln_omz_r.val * x + ln_omz_theta.val * y)/(r*r);
  330. const double t_y = (-ln_omz_r.val * y + ln_omz_theta.val * x)/(r*r);
  331. /* r = (1-z) ln(1-z)/z */
  332. const double r_x = (1.0 - x) * t_x + y * t_y;
  333. const double r_y = (1.0 - x) * t_y - y * t_x;
  334. real_dl->val = sum_re.val + r_x + 1.0;
  335. imag_dl->val = sum_im.val + r_y;
  336. real_dl->err = sum_re.err + 2.0*GSL_DBL_EPSILON*(fabs(real_dl->val) + fabs(r_x));
  337. imag_dl->err = sum_im.err + 2.0*GSL_DBL_EPSILON*(fabs(imag_dl->val) + fabs(r_y));
  338. return GSL_ERROR_SELECT_2(stat_s3, stat_log);
  339. }
  340. }
  341. /* Evaluate a series for Li_2(z) when |z| is near 1.
  342. * This is uniformly good away from z=1.
  343. *
  344. * Li_2(z) = Sum[ a^n/n! H_n(theta), {n, 0, Infinity}]
  345. *
  346. * where
  347. * H_n(theta) = Sum[ e^(i m theta) m^n / m^2, {m, 1, Infinity}]
  348. * a = ln(r)
  349. *
  350. * H_0(t) = Gl_2(t) + i Cl_2(t)
  351. * H_1(t) = 1/2 ln(2(1-c)) + I atan2(-s, 1-c)
  352. * H_2(t) = -1/2 + I/2 s/(1-c)
  353. * H_3(t) = -1/2 /(1-c)
  354. * H_4(t) = -I/2 s/(1-c)^2
  355. * H_5(t) = 1/2 (2 + c)/(1-c)^2
  356. * H_6(t) = I/2 s/(1-c)^5 (8(1-c) - s^2 (3 + c))
  357. */
  358. static
  359. int
  360. dilogc_series_3(
  361. const double r,
  362. const double x,
  363. const double y,
  364. gsl_sf_result * real_result,
  365. gsl_sf_result * imag_result
  366. )
  367. {
  368. const double theta = atan2(y, x);
  369. const double cos_theta = x/r;
  370. const double sin_theta = y/r;
  371. const double a = log(r);
  372. const double omc = 1.0 - cos_theta;
  373. const double omc2 = omc*omc;
  374. double H_re[7];
  375. double H_im[7];
  376. double an, nfact;
  377. double sum_re, sum_im;
  378. gsl_sf_result Him0;
  379. int n;
  380. H_re[0] = M_PI*M_PI/6.0 + 0.25*(theta*theta - 2.0*M_PI*fabs(theta));
  381. gsl_sf_clausen_e(theta, &Him0);
  382. H_im[0] = Him0.val;
  383. H_re[1] = -0.5*log(2.0*omc);
  384. H_im[1] = -atan2(-sin_theta, omc);
  385. H_re[2] = -0.5;
  386. H_im[2] = 0.5 * sin_theta/omc;
  387. H_re[3] = -0.5/omc;
  388. H_im[3] = 0.0;
  389. H_re[4] = 0.0;
  390. H_im[4] = -0.5*sin_theta/omc2;
  391. H_re[5] = 0.5 * (2.0 + cos_theta)/omc2;
  392. H_im[5] = 0.0;
  393. H_re[6] = 0.0;
  394. H_im[6] = 0.5 * sin_theta/(omc2*omc2*omc) * (8.0*omc - sin_theta*sin_theta*(3.0 + cos_theta));
  395. sum_re = H_re[0];
  396. sum_im = H_im[0];
  397. an = 1.0;
  398. nfact = 1.0;
  399. for(n=1; n<=6; n++) {
  400. double t;
  401. an *= a;
  402. nfact *= n;
  403. t = an/nfact;
  404. sum_re += t * H_re[n];
  405. sum_im += t * H_im[n];
  406. }
  407. real_result->val = sum_re;
  408. real_result->err = 2.0 * 6.0 * GSL_DBL_EPSILON * fabs(sum_re) + fabs(an/nfact);
  409. imag_result->val = sum_im;
  410. imag_result->err = 2.0 * 6.0 * GSL_DBL_EPSILON * fabs(sum_im) + Him0.err + fabs(an/nfact);
  411. return GSL_SUCCESS;
  412. }
  413. /* Calculate complex dilogarithm Li_2(z) in the fundamental region,
  414. * which we take to be the intersection of the unit disk with the
  415. * half-space x < MAGIC_SPLIT_VALUE. It turns out that 0.732 is a
  416. * nice choice for MAGIC_SPLIT_VALUE since then points mapped out
  417. * of the x > MAGIC_SPLIT_VALUE region and into another part of the
  418. * unit disk are bounded in radius by MAGIC_SPLIT_VALUE itself.
  419. *
  420. * If |z| < 0.98 we use a direct series summation. Otherwise z is very
  421. * near the unit circle, and the series_2 expansion is used; see above.
  422. * Because the fundamental region is bounded away from z = 1, this
  423. * works well.
  424. */
  425. static
  426. int
  427. dilogc_fundamental(double r, double x, double y, gsl_sf_result * real_dl, gsl_sf_result * imag_dl)
  428. {
  429. if(r > 0.98)
  430. return dilogc_series_3(r, x, y, real_dl, imag_dl);
  431. else if(r > 0.25)
  432. return dilogc_series_2(r, x, y, real_dl, imag_dl);
  433. else
  434. return dilogc_series_1(r, x, y, real_dl, imag_dl);
  435. }
  436. /* Compute Li_2(z) for z in the unit disk, |z| < 1. If z is outside
  437. * the fundamental region, which means that it is too close to z = 1,
  438. * then it is reflected into the fundamental region using the identity
  439. *
  440. * Li2(z) = -Li2(1-z) + zeta(2) - ln(z) ln(1-z).
  441. */
  442. static
  443. int
  444. dilogc_unitdisk(double x, double y, gsl_sf_result * real_dl, gsl_sf_result * imag_dl)
  445. {
  446. static const double MAGIC_SPLIT_VALUE = 0.732;
  447. static const double zeta2 = M_PI*M_PI/6.0;
  448. const double r = hypot(x, y);
  449. if(x > MAGIC_SPLIT_VALUE)
  450. {
  451. /* Reflect away from z = 1 if we are too close. The magic value
  452. * insures that the reflected value of the radius satisfies the
  453. * related inequality r_tmp < MAGIC_SPLIT_VALUE.
  454. */
  455. const double x_tmp = 1.0 - x;
  456. const double y_tmp = - y;
  457. const double r_tmp = hypot(x_tmp, y_tmp);
  458. /* const double cos_theta_tmp = x_tmp/r_tmp; */
  459. /* const double sin_theta_tmp = y_tmp/r_tmp; */
  460. gsl_sf_result result_re_tmp;
  461. gsl_sf_result result_im_tmp;
  462. const int stat_dilog = dilogc_fundamental(r_tmp, x_tmp, y_tmp, &result_re_tmp, &result_im_tmp);
  463. const double lnz = log(r); /* log(|z|) */
  464. const double lnomz = log(r_tmp); /* log(|1-z|) */
  465. const double argz = atan2(y, x); /* arg(z) assuming principal branch */
  466. const double argomz = atan2(y_tmp, x_tmp); /* arg(1-z) */
  467. real_dl->val = -result_re_tmp.val + zeta2 - lnz*lnomz + argz*argomz;
  468. real_dl->err = result_re_tmp.err;
  469. real_dl->err += 2.0 * GSL_DBL_EPSILON * (zeta2 + fabs(lnz*lnomz) + fabs(argz*argomz));
  470. imag_dl->val = -result_im_tmp.val - argz*lnomz - argomz*lnz;
  471. imag_dl->err = result_im_tmp.err;
  472. imag_dl->err += 2.0 * GSL_DBL_EPSILON * (fabs(argz*lnomz) + fabs(argomz*lnz));
  473. return stat_dilog;
  474. }
  475. else
  476. {
  477. return dilogc_fundamental(r, x, y, real_dl, imag_dl);
  478. }
  479. }
  480. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  481. int
  482. gsl_sf_dilog_e(const double x, gsl_sf_result * result)
  483. {
  484. if(x >= 0.0) {
  485. return dilog_xge0(x, result);
  486. }
  487. else {
  488. gsl_sf_result d1, d2;
  489. int stat_d1 = dilog_xge0( -x, &d1);
  490. int stat_d2 = dilog_xge0(x*x, &d2);
  491. result->val = -d1.val + 0.5 * d2.val;
  492. result->err = d1.err + 0.5 * d2.err;
  493. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  494. return GSL_ERROR_SELECT_2(stat_d1, stat_d2);
  495. }
  496. }
  497. int
  498. gsl_sf_complex_dilog_xy_e(
  499. const double x,
  500. const double y,
  501. gsl_sf_result * real_dl,
  502. gsl_sf_result * imag_dl
  503. )
  504. {
  505. const double zeta2 = M_PI*M_PI/6.0;
  506. const double r2 = x*x + y*y;
  507. if(y == 0.0)
  508. {
  509. if(x >= 1.0)
  510. {
  511. imag_dl->val = -M_PI * log(x);
  512. imag_dl->err = 2.0 * GSL_DBL_EPSILON * fabs(imag_dl->val);
  513. }
  514. else
  515. {
  516. imag_dl->val = 0.0;
  517. imag_dl->err = 0.0;
  518. }
  519. return gsl_sf_dilog_e(x, real_dl);
  520. }
  521. else if(fabs(r2 - 1.0) < GSL_DBL_EPSILON)
  522. {
  523. /* Lewin A.2.4.1 and A.2.4.2 */
  524. const double theta = atan2(y, x);
  525. const double term1 = theta*theta/4.0;
  526. const double term2 = M_PI*fabs(theta)/2.0;
  527. real_dl->val = zeta2 + term1 - term2;
  528. real_dl->err = 2.0 * GSL_DBL_EPSILON * (zeta2 + term1 + term2);
  529. return gsl_sf_clausen_e(theta, imag_dl);
  530. }
  531. else if(r2 < 1.0)
  532. {
  533. return dilogc_unitdisk(x, y, real_dl, imag_dl);
  534. }
  535. else
  536. {
  537. /* Reduce argument to unit disk. */
  538. const double r = sqrt(r2);
  539. const double x_tmp = x/r2;
  540. const double y_tmp = -y/r2;
  541. /* const double r_tmp = 1.0/r; */
  542. gsl_sf_result result_re_tmp, result_im_tmp;
  543. const int stat_dilog =
  544. dilogc_unitdisk(x_tmp, y_tmp, &result_re_tmp, &result_im_tmp);
  545. /* Unwind the inversion.
  546. *
  547. * Li_2(z) + Li_2(1/z) = -zeta(2) - 1/2 ln(-z)^2
  548. */
  549. const double theta = atan2(y, x);
  550. const double theta_abs = fabs(theta);
  551. const double theta_sgn = ( theta < 0.0 ? -1.0 : 1.0 );
  552. const double ln_minusz_re = log(r);
  553. const double ln_minusz_im = theta_sgn * (theta_abs - M_PI);
  554. const double lmz2_re = ln_minusz_re*ln_minusz_re - ln_minusz_im*ln_minusz_im;
  555. const double lmz2_im = 2.0*ln_minusz_re*ln_minusz_im;
  556. real_dl->val = -result_re_tmp.val - 0.5 * lmz2_re - zeta2;
  557. real_dl->err = result_re_tmp.err + 2.0*GSL_DBL_EPSILON*(0.5 * fabs(lmz2_re) + zeta2);
  558. imag_dl->val = -result_im_tmp.val - 0.5 * lmz2_im;
  559. imag_dl->err = result_im_tmp.err + 2.0*GSL_DBL_EPSILON*fabs(lmz2_im);
  560. return stat_dilog;
  561. }
  562. }
  563. int
  564. gsl_sf_complex_dilog_e(
  565. const double r,
  566. const double theta,
  567. gsl_sf_result * real_dl,
  568. gsl_sf_result * imag_dl
  569. )
  570. {
  571. const double cos_theta = cos(theta);
  572. const double sin_theta = sin(theta);
  573. const double x = r * cos_theta;
  574. const double y = r * sin_theta;
  575. return gsl_sf_complex_dilog_xy_e(x, y, real_dl, imag_dl);
  576. }
  577. int
  578. gsl_sf_complex_spence_xy_e(
  579. const double x,
  580. const double y,
  581. gsl_sf_result * real_sp,
  582. gsl_sf_result * imag_sp
  583. )
  584. {
  585. const double oms_x = 1.0 - x;
  586. const double oms_y = - y;
  587. return gsl_sf_complex_dilog_xy_e(oms_x, oms_y, real_sp, imag_sp);
  588. }
  589. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  590. #include "gsl_specfunc__eval.h"
  591. double gsl_sf_dilog(const double x)
  592. {
  593. EVAL_RESULT(gsl_sf_dilog_e(x, &result));
  594. }