#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; } double evaluate_polynomial (size_t size, double P[], double x) { double value = 0; int deg = size-1; for (int i=deg; i>=0; i--) { value += P[i]*pow(x,i); } return value; } long double cyl_bessel_0 (long double x) { if (x>35) { //accurate to 1/1000 long double ret = expl(-x)*sqrt(M_PI/(2*x)) * (1 - 1/(8*x)); // limiting expression //std::cout <<"Using limiting expression, bessel_0 = " << ret << std::endl; //debugging return ret; } static double P1[] = { 2.4708152720399552679e+03, 5.9169059852270512312e+03, 4.6850901201934832188e+02, 1.1999463724910714109e+01, 1.3166052564989571850e-01, 5.8599221412826100000e-04 }; static double Q1[] = { 2.1312714303849120380e+04, -2.4994418972832303646e+02, 1.0 }; static double P2[] = { -1.6128136304458193998e+06, -3.7333769444840079748e+05, -1.7984434409411765813e+04, -2.9501657892958843865e+02, -1.6414452837299064100e+00 }; static double Q2[] = { -1.6128136304458193998e+06, 2.9865713163054025489e+04, -2.5064972445877992730e+02, 1.0 }; static double P3[] = { 1.1600249425076035558e+02, 2.3444738764199315021e+03, 1.8321525870183537725e+04, 7.1557062783764037541e+04, 1.5097646353289914539e+05, 1.7398867902565686251e+05, 1.0577068948034021957e+05, 3.1075408980684392399e+04, 3.6832589957340267940e+03, 1.1394980557384778174e+02 }; static double Q3[] = { 9.2556599177304839811e+01, 1.8821890840982713696e+03, 1.4847228371802360957e+04, 5.8824616785857027752e+04, 1.2689839587977598727e+05, 1.5144644673520157801e+05, 9.7418829762268075784e+04, 3.1474655750295278825e+04, 4.4329628889746408858e+03, 2.0013443064949242491e+02, 1.0 }; double factor, r, r1, r2; long double value; if (x < 0) return -1; //error if (x == 0) return -1; //error if (x <= 1) { double y = x*x; r1 = evaluate_polynomial(sizeof(P1)/sizeof(P1[0]),P1,y) / evaluate_polynomial(sizeof(Q1)/sizeof(Q1[0]),Q1,y); r2 = evaluate_polynomial(sizeof(P2)/sizeof(P2[0]),P2,y) / evaluate_polynomial(sizeof(Q2)/sizeof(Q2[0]),Q2,y); factor = log(x); value = r1 - factor * r2; } else { double y = 1/x; r = evaluate_polynomial(sizeof(P3)/sizeof(P3[0]),P3,y) / evaluate_polynomial(sizeof(Q3)/sizeof(Q3[0]),Q3,y); factor = exp(-x)/sqrt(x); value = factor * r; } //std::cout << "Using rational approximation, bessel_0 = " << value << std::endl; //debugging return value; } long double cyl_bessel_1 (long double x) { if (x>35) { //accurate to 1/1000 long double ret = expl(-x)*sqrt(M_PI/(2*x)) * (1 + 3/(8*x)); // limiting expression //std::cout << "Using limiting expression, bessel_1 = " << ret << std::endl; //debugging return ret; } static double P1[] = { -2.2149374878243304548e+06, 7.1938920065420586101e+05, 1.7733324035147015630e+05, 7.1885382604084798576e+03, 9.9991373567429309922e+01, 4.8127070456878442310e-01 }; static double Q1[] = { -2.2149374878243304548e+06, 3.7264298672067697862e+04, -2.8143915754538725829e+02, 1.0 }; static double P2[] = { 0.0, -1.3531161492785421328e+06, -1.4758069205414222471e+05, -4.5051623763436087023e+03, -5.3103913335180275253e+01, -2.2795590826955002390e-01 }; static double Q2[] { -2.7062322985570842656e+06, 4.3117653211351080007e+04, -3.0507151578787595807e+02, 1.0 }; static double P3[] = { 2.2196792496874548962e+00, 4.4137176114230414036e+01, 3.4122953486801312910e+02, 1.3319486433183221990e+03, 2.8590657697910288226e+03, 3.4540675585544584407e+03, 2.3123742209168871550e+03, 8.1094256146537402173e+02, 1.3182609918569941308e+02, 7.5584584631176030810e+00, 6.4257745859173138767e-02 }; static double Q3[] = { 1.7710478032601086579e+00, 3.4552228452758912848e+01, 2.5951223655579051357e+02, 9.6929165726802648634e+02, 1.9448440788918006154e+03, 2.1181000487171943810e+03, 1.2082692316002348638e+03, 3.3031020088765390854e+02, 3.6001069306861518855e+01, 1.0 }; double factor, r, r1, r2, y; long double value; if (x < 0) return -1; //error if (x == 0) return -1; //error if (x <= 1) { y = x*x; r1 = evaluate_polynomial(sizeof(P1)/sizeof(P1[0]),P1,y) / evaluate_polynomial(sizeof(Q1)/sizeof(Q1[0]),Q1,y); r2 = evaluate_polynomial(sizeof(P2)/sizeof(P2[0]),P2,y) / evaluate_polynomial(sizeof(Q2)/sizeof(Q2[0]),Q2,y); factor = log(x); value = (r1 + factor*r2)/x; } else { y = 1/x; r = evaluate_polynomial(sizeof(P3)/sizeof(P3[0]),P3,y) / evaluate_polynomial(sizeof(Q3)/sizeof(Q3[0]),Q3,y); factor = exp(-x)/sqrt(x); value = factor*r; } //std::cout << "Using rational approximation, bessel_1 = " << value << std::endl; //debugging return value; } long double cyl_bessel_2 (long double x) { return 2*1/x * cyl_bessel_1(x) + cyl_bessel_0(x); } }