#include "ATOOLS/Math/MathTools.H" #include "ATOOLS/Org/Message.H" namespace ATOOLS { // calculates the logarithm of the Gammafunction double Gammln(double xx) { double x,y,tmp,ser; static double cof[6]={76.18009172947146,-86.50532032941677, 24.01409824083091,-1.231739572450155, 0.1208650973866179e-2,-0.5395239384953e-5}; short int j; y=x=xx; tmp=x+5.5; tmp -= (x+0.5)*log(tmp); ser=1.000000000190015; for (j=0;j<=5;j++) ser += cof[j]/++y; return -tmp+log(2.5066282746310005*ser/x); } // (C) Copr. 1986-92 Numerical Recipes Software VsXz&v%120(9p+45$j3D. double ReIncompleteGamma0(double x, double prec) { const double euler_gamma=GAMMA_E; /* Fuer die unvollstaendige Gammafunktion Gamma(0,x) (x reel) existieren Entwicklungen sowohl fuer positive als auch fuer negative x. Fuer positive x kann man um grosse x entwickeln, fuer negative x nur um kleine x: x>0 x->infinity Gamma(0,x) = - Exp[-x] * ( Sum_n=1^Infty (n-1)! / (-x)^n) x->0 Re[Gamma(0,x)] = - EulerGamma - Log[Abs[x]] - Sum_n=1^Infty(-x)^n/(n*n!) Im = - I Pi fuer x<0 Im = 0 fuer x>0 z.B. Gamma(0,-.1) = 1.6228128139692766750 - 3.1415926535897932385 I Gamma(0,.1) = 1.8229239584193906661 Fuer positive argumente ist die funktion alternierend */ double sum= -euler_gamma -log(dabs(x)); double i = 1; double ai = -x; for (;;) { sum-=ai; ai*=-x*i/sqr(i+1); i+=1.; if (dabs(ai/sum)2000) { std::cerr<<" ERROR in ReIncompletGamma0("<1. ) { return -DiLog(1./x)+M_PI*M_PI/3.-0.5*sqr(log(x)); } x = 1.-x; double w, y, z; int flag; if( x == 1.0 ) return( 0.0 ); if( x == 0.0 ) return( M_PI*M_PI/6.0 ); flag = 0; if( x > 2.0 ) { x = 1.0/x; flag |= 2; } if( x > 1.5 ) { w = (1.0/x) - 1.0; flag |= 2; } else if( x < 0.5 ) { w = -x; flag |= 1; } else w = x - 1.0; y = -w * polevl( w, cof_A, 7) / polevl( w, cof_B, 7 ); if( flag & 1 ) y = (M_PI * M_PI)/6.0 - log(x) * log(1.0-x) - y; if( flag & 2 ) { z = log(x); y = -0.5 * z * z - y; } return y; } Complex DiLog(const Complex& x) { // only calculates for real arguments // -> be careful with discontinuity along pos. real axis if (imag(x) == 0.) { std::cout<<"use real dilog ..."< precission) || (imag(next)/imag(sum) > precission))*/(i < 100) { ++i; prod *= x; next = prod/((double)(i*i)); sum += next; } std::cout<<"number of iterations: "< convfactor) { // ++i; // prod *= x; // next = prod/sqr((double)(i*(i+1)*(i+2))); // sum += next; // } // return factor*sum + 4.*x + 23./4.*x*x + 3.*(1.-x*x)*log(1.-x); } else if (abs(x) > 1./radius) { std::cout< precission) || (imag(next)/imag(sum) > precission)) && (i<35)) { ++i; sum += next; prod *= y; next = prod*A[i]; } std::cout<<"number of iterations: "< 1.) { // continued fraction double b=x+n; double c=1.e30; // 1./DBL_MIN () double d=1./b; double h=d; for (int i=1; i <= MaximumIterations; i++) { double a = -i*(n-1+i); b+=2.; d=1./(a*d + b); c=b + a/c; double del=c*d; h *= del; if (fabs(del-1.0) < eps) { return h*exp(-x); } } msg_Error() << "Continued fraction failed in ExpIntegral()! x=" << x << std::endl; } else { // series evaluation double result = (n-1) ? 1./(n-1) : -log(x)-EulerMascheroni; double fact=1.; for (int i=1; i <= MaximumIterations; i++) { fact *= -x/i; double del = 0.; if (i != (n - 1)) del = -fact/(i-n+1); else { double psi = -EulerMascheroni; for (int j=1; j < (n - 1); j++) { psi += 1./j; } del=fact*(-log(x)+psi); } result += del; if (fabs(del) < fabs(result)*eps) { return result; } } msg_Error() << "Series failed in ExpIntegral()! x=" << x << std::endl; } } msg_Error() << "Exponential Integral Calculation failed! x=" << x << std::endl; return 0.0; } }