You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ABACUS_Spec_Fns.h 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /**********************************************************
  2. This software is part of J.-S. Caux's ABACUS library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: ABACUS_Spec_Fns.h
  6. Purpose: Defines special math functions.
  7. ***********************************************************/
  8. #ifndef ABACUS_SPEC_FNS_H
  9. #define ABACUS_SPEC_FNS_H
  10. #include "ABACUS.h"
  11. namespace ABACUS {
  12. inline DP Cosine_Integral (DP x)
  13. {
  14. // Returns the Cosine integral -\int_x^\infty dt \frac{\cos t}{t}
  15. // Refer to GR[6] 8.23
  16. if (x <= 0.0) {
  17. std::cout << "Cosine_Integral called with real argument "
  18. << x << " <= 0, which is ill-defined because of the branch cut." << std::endl;
  19. ABACUSerror("");
  20. }
  21. else if (x < 15.0) { // Use power series expansion
  22. // Ci (x) = gamma + \ln x + \sum_{n=1}^\infty (-1)^n x^{2n}/(2n (2n)!).
  23. int n = 1;
  24. DP minonetothen = -1.0;
  25. DP logxtothetwon = 2.0 * log(x);
  26. DP twologx = 2.0 * log(x);
  27. DP logtwonfact = log(2.0);
  28. DP series = minonetothen * exp(logxtothetwon - log(2.0 * n) - logtwonfact);
  29. DP term_n;
  30. do {
  31. n += 1;
  32. minonetothen *= -1.0;
  33. logxtothetwon += twologx;
  34. logtwonfact += log((2.0 * n - 1.0) * 2.0 * n);
  35. term_n = minonetothen * exp(logxtothetwon - log(2.0 * n) - logtwonfact);
  36. series += term_n;
  37. } while (fabs(term_n) > 1.0e-16);
  38. return(Euler_Mascheroni + log(x) + series);
  39. }
  40. else { // Use high x power series
  41. // Ci (x) = \frac{\sin x}{x} \sum_{n=0}^\infty (-1)^n (2n)! x^{-2n}
  42. // - \frac{\cos x}{x} \sum_{n=0}^\infty (-1)^n (2n+1)! x^{-2n-1}
  43. int n = 0;
  44. DP minonetothen = 1.0;
  45. DP logxtothetwon = 0.0;
  46. DP logxtothetwonplus1 = log(x);
  47. DP twologx = 2.0 * log(x);
  48. DP logtwonfact = 0.0;
  49. DP logtwonplus1fact = 0.0;
  50. DP series1 = minonetothen * exp(logtwonfact - logxtothetwon);
  51. DP series2 = minonetothen * exp(logtwonplus1fact - logxtothetwonplus1);
  52. do {
  53. n += 1;
  54. minonetothen *= -1.0;
  55. logxtothetwon += twologx;
  56. logxtothetwonplus1 += twologx;
  57. logtwonfact += log((2.0 * n - 1.0) * 2.0 * n);
  58. logtwonplus1fact += log(2.0 * n * (2.0 * n + 1));
  59. series1 += minonetothen * exp(logtwonfact - logxtothetwon);
  60. series2 += minonetothen * exp(logtwonplus1fact - logxtothetwonplus1);
  61. } while (n < 12);
  62. return((sin(x)/x) * series1 - (cos(x)/x) * series2);
  63. }
  64. return(log(-1.0));
  65. }
  66. /*********** Jacobi Theta functions *********/
  67. inline DP Jacobi_Theta_1_q (DP u, DP q) {
  68. // Uses the summation formula.
  69. // theta_1 (x) = 2 \sum_{n=1}^\infty (-1)^{n+1} q^{(n-1/2)^2} \sin (2n-1)u
  70. // in which q is the nome. (GR 8.180.1)
  71. // We always evaluate to numerical accuracy.
  72. if (q >= 1.0) ABACUSerror("Jacobi_Theta_1_q function called with q > 1.");
  73. DP answer = 0.0;
  74. DP contrib = 0.0;
  75. DP qtonminhalfsq = pow(q, 0.25); // this will be q^{(n-1/2)^2}
  76. DP qtotwon = pow(q, 2.0); // this will be q^{2n}
  77. DP qsq = q*q;
  78. int n = 1;
  79. do {
  80. contrib = (n % 2 ? 2.0 : -2.0) * qtonminhalfsq * sin((2.0*n - 1.0)*u);
  81. answer += contrib;
  82. qtonminhalfsq *= qtotwon;
  83. qtotwon *= qsq;
  84. n++;
  85. } while (fabs(contrib/answer) > MACHINE_EPS);
  86. return(answer);
  87. }
  88. inline std::complex<DP> ln_Jacobi_Theta_1_q (std::complex<DP> u, std::complex<DP> q) {
  89. // This uses the product representation
  90. // \theta_1 (x) = 2 q^{1/4} \sin{u} \prod_{n=1}^\infty (1 - 2 q^{2n} \cos 2u + q^{4n}) (1 - q^{2n})
  91. // (GR 8.181.2)
  92. std::complex<DP> contrib = 0.0;
  93. std::complex<DP> qtotwon = q*q; // this will be q^{2n}
  94. std::complex<DP> qsq = q*q;
  95. std::complex<DP> twocos2u = 2.0 * cos(2.0*u);
  96. int n = 1;
  97. std::complex<DP> answer = log(2.0 * sin(u)) + 0.25 * log(q);
  98. do {
  99. contrib = log((1.0 - twocos2u * qtotwon + qtotwon * qtotwon) * (1.0 - qtotwon));
  100. answer += contrib;
  101. qtotwon *= qsq;
  102. n++;
  103. } while (abs(contrib) > 1.0e-12);
  104. return(answer);
  105. }
  106. /************ Barnes function ************/
  107. inline DP ln_Gamma_for_Barnes_G_RE (Vect_DP args)
  108. {
  109. return(real(ln_Gamma(std::complex<double>(args[0]))));
  110. }
  111. inline DP ln_Barnes_G_RE (DP z)
  112. {
  113. // Implementation according to equation (28) of 2004_Adamchik_CPC_157
  114. // Restricted to real arguments.
  115. Vect_DP args (0.0, 2);
  116. DP req_rel_prec = 1.0e-6;
  117. DP req_abs_prec = 1.0e-6;
  118. int max_nr_pts = 10000;
  119. Integral_result integ_ln_Gamma = Integrate_optimal (ln_Gamma_for_Barnes_G_RE, args, 0, 0.0, z - 1.0, req_rel_prec, req_abs_prec, max_nr_pts);
  120. return(0.5 * (z - 1.0) * (2.0 - z + logtwoPI)
  121. + (z - 1.0) * real(ln_Gamma(std::complex<double>(z - 1.0))) - integ_ln_Gamma.integ_est);
  122. }
  123. } // namespace ABACUS
  124. #endif