www.pudn.com > 1.rar > Mathutil.cpp


/////////////////////////////////////////////////////////////////////////////// 
//                                                                           // 
// Dateiname: MATHUTIL.CPP                                                   // 
//                                                                           // 
// Autor:     Andreas Jäger, Friedrich-Schiller-Universität Jena             // 
//                                                                           // 
// System:    WIN_RWPM.EXE und WINLRWPM.EXE                                  // 
//                                                                           // 
// Beschreibung: Mathematische Routinen                                      // 
//                                                                           // 
// Hinweise:                                                                 // 
//                                                                           // 
/////////////////////////////////////////////////////////////////////////////// 
#include "stdafx.h" 
#include  
#include "mathutil.h" 
 
long Fixl(long double x) 
{ 
#pragma warning ( disable : 4244 ) 
	return x; 
#pragma warning ( default : 4244 ) 
} 
 
long double Reml(long double x, long double y) 
{ 
	return x-y*Fixl(x/y); 
} 
 
long Fix(double x) 
{ 
#pragma warning ( disable : 4244 ) 
	return x; 
#pragma warning ( default : 4244 ) 
} 
 
double Rem(double x, double y) 
{ 
	return x-y*Fix(x/y); 
} 
 
bool Rational(long double x, long maxtest, long double TOL, long& zaehler, long& nenner) 
{ 
#pragma warning ( disable : 4244 ) 
	long y = x; 
#pragma warning ( default : 4244 ) 
	if (fabsl(y - x) < TOL) 
	{ 
		zaehler = y; 
		nenner = 1L; 
		return true; 
	} 
	for (long p=2; p<=maxtest; p++) 
	{ 
#pragma warning ( disable : 4244 ) 
		y = x*p; 
#pragma warning ( default : 4244 ) 
		if (fabsl(y - p*x) < TOL) 
		{ 
			zaehler = y; 
			nenner = p; 
			return true; 
		} 
	} 
	return false; 
} 
 
long ggT(long x, long y) 
{ 
	for (long r = x%y; r!=0; x=y, y=r, r=x%y) 
	{ 
	} 
	return abs(y); 
	 
} 
 
long kgV(long x, long y) 
{ 
	long z = x; 
	z /= ggT(x,y); 
	return z*y; 
} 
 
long Fak(long x) 
{ 
	long s = 1; 
	for (int i=2;i <= x;i++) s *= i; 
	return s; 
} 
 
// Diese Version nur für gutmütige n, m verwenden 
long BinKoeff(long n, long m) 
{ 
	long p = 1; 
	long i; 
	for (i=n; i>=n-m+1; i--) 
	{ 
		p *= i; 
	} 
	for (i=2; i<=m; i++) 
	{ 
		p /= i; 
	} 
	return p; 
} 
 
long double BinKoeffEx(long double ny, long k) 
{ 
	long double t; 
    long i; 
 
	t = 1; 
	for (i=1; i<=k; i++) 
	{ 
		t *= (ny-i+1)/i; 
	} 
	return t; 
} 
 
#define Fib_Rho (0.5*(1+sqrtl(5))) 
long double Fibonacci(int n) 
{ 
	return (powl(Fib_Rho, n) - powl(1-Fib_Rho, n)) / (2.0 * Fib_Rho - 1); 
} 
 
// Berechnet eine nichtkrumme Zahl im Intervall x1<=x<=x2 
// z.B. 1 für x1=0.6, x2=3.5 
long double NichtKrumm(long double x1, long double x2) 
{ 
	if (x1*x2<=0) return 0.0L; 
	long double dist = fabsl(x1 - x2); 
	if (dist <= 1E-300) return x1; // Sicherheit vor Überläufen 
#pragma warning ( disable : 4244 ) 
	int l = floorl(log10l(dist)); 
#pragma warning ( default : 4244 ) 
	long double d1 = ((l<0) ? (1.0/powl(10.0, -l)) : powl(10.0, l)); // "Maßeinheit" 
	while (floorl(min(x1,x2)/(10.0*d1)) 0) and (Rem(k,2)=0) then t := t + 2*bk; 
      end; 
      if (k = 0) then t := t + bk; 
 
      { Normalizing condition, J0(x) + 2*J2(x) + 2*J4(x) + ... = 1} 
      J := bn/t; 
 
      {Restore results for x = 0; J0(0) = 1, Jn(0) = 0 for n > 0} 
 
      J := (1-z)*J + z*Integer(n=0); 
 
      Besseln:=J; 
end; 
*/ 
 
long double FGammal(long double x) 
{ 
	long double MaxGammaNumber = 1700; 
	long double inf = 233; 
	long double sig,fact,y,y1,Res,z,xnum,xden,gam,ysq,sum; 
    int i,n; 
 
       long double eps=1e-20L; 
       //{Constants for Aproximation of Gamma(x)} 
 
	   long double   p [] = {0,-1.71618513886549492533811e+0,  2.47656508055759199108314e+1, 
                                     -3.79804256470945635097577e+2,  6.29331155312818442661052e+2, 
                                      8.66966202790413211295064e+2, -3.14512729688483675254357e+4, 
									  -3.61444134186911729807069e+4,  6.64561438202405440627855e+4}; 
		long double q[] = {0,-3.08402300119738975254353e+1,  3.15350626979604161529144e+2, 
                                     -1.01515636749021914166146e+3, -3.10777167157231109440444e+3, 
                                      2.25381184209801510330112e+4,  4.75584627752788110767815e+3, 
									  -1.34659959864969306392456e+5, -1.15132259675553483497211e+5}; 
		long double c[] = {0, -1.910444077728e-03          ,  8.4171387781295e-04, 
                                     -5.952379913043012e-04       ,  7.93650793500350248e-04, 
                                     -2.777777777777681622553e-03 ,  8.333333333333333331554247e-02, 
									 5.7083835261e-03}; 
	sig = 1; 
	fact = 1; 
	y    = x; 
	//{ Negative x } 
 
	if (y <= 0) 
	{ 
		y = -x; 
		if (Reml(Fixl(y),2) != 0)  
			sig = -1; 
		Res = Reml(y,1); 
		if (Res != 0) 
			fact = -PI/sinl(PI*Res); 
		else  
		{ 
			//{Pole at negative integers} 
			fact = inf; 
		} 
		y = y + 1; 
	} 
 
	if (y  < eps) 
		gam=1/y;   //{ Small x } 
 
	if ((y > eps) && (y <= 12)) 
	{ 
		//{ eps < x <= 12 } 
		y1 = y; 
		if (y < 1) 
		{ 
			n = 0; 
			z = y; 
			y = y + 1; 
		} 
		else 
		{ 
			n = Fixl(y) - 1; 
			y = y - n; 
			z = y - 1; 
		} 
          
		//{Rational approximation for 1.0 < x < 2.0} 
		xnum = 0; 
		xden = 1; 
		for (i = 1; i<=8; i++) 
		{ 
			xnum = (xnum + p[i]) * z; 
			xden = xden * z + q[i]; 
		} 
		gam = xnum / xden + 1; 
		if (y > y1) 
		{ 
			//{ Adjust result for 0.0 < x < 1.0} 
			gam = gam / y1; 
		} 
		else 
		{ 
            if (y < y1) 
			{ 
				//{ Adjust result for 2.0 < x < 12.0} 
				for (i=1; i<=n; i++) 
				{ 
                   gam = gam * y; 
                   y = y + 1; 
				} 
            } 
		} 
	} 
	//{ Different rational approximation for 12 < x < xbig} 
	if ((y > 12) && (y <= MaxGammaNumber)) 
	{ 
		ysq = y * y; 
		sum = c[7]; 
		for (i=1; i<=6; i++) 
		{ 
			sum = sum/ysq + c[i]; 
		} 
		sum = sum/y - y + logl(2*PI)/2 + (y-0.5L)*logl(y); 
		gam = expl(sum);                   //{Large x} 
	} 
	//{Final adjustments  } 
	if (y > MaxGammaNumber) 
		gam = inf; 
 
	gam = sig*gam; 
	if (fact != 1 ) 
		gam = fact / gam; 
	if (x==(int)x) 
		gam = (int)gam; 
	return gam; 
} 
 
double FGamma(double x) 
{ 
	double MaxGammaNumber = 1700; 
	double inf = 233; 
	double sig,fact,y,y1,Res,z,xnum,xden,gam,ysq,sum; 
    int i,n; 
 
       double eps=1e-20L; 
       //{Constants for Aproximation of Gamma(x)} 
 
	   double   p [] = {0,-1.71618513886549492533811e+0,  2.47656508055759199108314e+1, 
                                     -3.79804256470945635097577e+2,  6.29331155312818442661052e+2, 
                                      8.66966202790413211295064e+2, -3.14512729688483675254357e+4, 
									  -3.61444134186911729807069e+4,  6.64561438202405440627855e+4}; 
		double q[] = {0,-3.08402300119738975254353e+1,  3.15350626979604161529144e+2, 
                                     -1.01515636749021914166146e+3, -3.10777167157231109440444e+3, 
                                      2.25381184209801510330112e+4,  4.75584627752788110767815e+3, 
									  -1.34659959864969306392456e+5, -1.15132259675553483497211e+5}; 
		double c[] = {0, -1.910444077728e-03          ,  8.4171387781295e-04, 
                                     -5.952379913043012e-04       ,  7.93650793500350248e-04, 
                                     -2.777777777777681622553e-03 ,  8.333333333333333331554247e-02, 
									 5.7083835261e-03}; 
	sig = 1; 
	fact = 1; 
	y    = x; 
	//{ Negative x } 
 
	if (y <= 0) 
	{ 
		y = -x; 
		if (Rem(Fix(y),2) != 0)  
			sig = -1; 
		Res = Rem(y,1); 
		if (Res != 0) 
			fact = -PI_/sin(PI_*Res); 
		else  
		{ 
			//{Pole at negative integers} 
			fact = inf; 
		} 
		y = y + 1; 
	} 
 
	if (y  < eps) 
		gam=1/y;   //{ Small x } 
 
	if ((y > eps) && (y <= 12)) 
	{ 
		//{ eps < x <= 12 } 
		y1 = y; 
		if (y < 1) 
		{ 
			n = 0; 
			z = y; 
			y = y + 1; 
		} 
		else 
		{ 
			n = Fix(y) - 1; 
			y = y - n; 
			z = y - 1; 
		} 
          
		//{Rational approximation for 1.0 < x < 2.0} 
		xnum = 0; 
		xden = 1; 
		for (i = 1; i<=8; i++) 
		{ 
			xnum = (xnum + p[i]) * z; 
			xden = xden * z + q[i]; 
		} 
		gam = xnum / xden + 1; 
		if (y > y1) 
		{ 
			//{ Adjust result for 0.0 < x < 1.0} 
			gam = gam / y1; 
		} 
		else 
		{ 
            if (y < y1) 
			{ 
				//{ Adjust result for 2.0 < x < 12.0} 
				for (i=1; i<=n; i++) 
				{ 
                   gam = gam * y; 
                   y = y + 1; 
				} 
            } 
		} 
	} 
	//{ Different rational approximation for 12 < x < xbig} 
	if ((y > 12) && (y <= MaxGammaNumber)) 
	{ 
		ysq = y * y; 
		sum = c[7]; 
		for (i=1; i<=6; i++) 
		{ 
			sum = sum/ysq + c[i]; 
		} 
		sum = sum/y - y + log(2*PI)/2 + (y-0.5)*log(y); 
		gam = exp(sum);                   //{Large x} 
	} 
	//{Final adjustments  } 
	if (y > MaxGammaNumber) 
		gam = inf; 
 
	gam = sig*gam; 
	if (fact != 1 ) 
		gam = fact / gam; 
	if (x==(int)x) 
		gam = (int)gam; 
	return gam; 
} 
 
 
/* 
long double Bessela(long double nu, long double x); 
{ 
	long double xz,KMIN,z,t,q1,p1,r,mu,l,k,s,y,J,Ja,da,Jp,dp,digits; 
    int oka,okp; 
 
	xz = (x==0) ? 1 : 0; 
    x = x + xz; 
 
      //{ Asymptotic series } 
      KMIN = 12;//{ Try the series for at least KMIN/2 terms.} 
      z = (-1)/Powl(8*x,2.0L); 
      t = 0*x; 
      q1 = t; 
      t = t + 1; 
      p1 = t; 
      r = abs(t); 
      mu = 2*nu; 
      k = 0; 
      l = -1; 
      oka = Integer(x > 0.9*nu); 
      while ((FAbs(t) > eps*Max(FAbs(p1),FAbs(q1))) and Boolean(oka)) do begin 
         s := t; 
         k := k+1; 
         l := l+2; 
         t := (mu-l)*(mu+l)/k*t; 
         q1 := q1 + t; 
         k := k+1; 
         l := l+2; 
         t := (mu-l)*(mu+l)/k*t*z; 
         p1 := p1+t; 
         r := Max(r,FAbs(t)); 
         if k >= 2*KMIN then oka := oka * Integer(FAbs(t) <= 5*FAbs(s)); 
      end; 
      q1 := q1/(8*x); 
      y := x - (2*nu+1)*PI/4; 
      Ja  := FSqrt((2)/(PI*x)) * (p1*FCos(y) - q1*FSin(y)); 
      da  := Max(oka*FLg(Max(FAbs(p1),FAbs(q1))/(eps*FAbs(r))),0); 
      oka := oka*Integer(da > 0); 
 
     { If necessary, use power series expansion. 
        Requires the gamma function from another M file} 
      okp := Integer(da < 12); 
      if Boolean(okp) then begin 
         t := okp * FPower(x/2,nu) / Gamma(nu+1); 
         s := t; 
         r := abs(t); 
         z := -Sqr(x/2); 
         k := 0; 
         while ((abs(t) > eps*FAbs(s)) and Boolean(okp)) do begin 
            k := k + 1; 
            t := z*t/(k*(nu+k)); 
            s := s + t; 
            r := Max(r,abs(t)); 
            okp := okp * Integer((eps*FAbs(r) <= FAbs(s))); 
         end; 
         Jp := s; 
         dp := Max(okp*FLg((1-okp+FAbs(s))/(1-okp+eps*FAbs(r))),0); 
         okp := okp*Integer(dp > 0)*Integer(dp>da); 
         oka := oka*Integer(da>=dp); 
         digits := oka*da + okp*dp; 
         J := oka*Ja + okp*Jp + (0)/digits;end 
      else begin 
         J := Ja; 
         digits := da; 
      end; 
 
      { Restore results for x = 0; J0(0) = 1, Jnu(0) = 0 for nu > 0.} 
      Bessela := (1-xz)*J + xz*Integer(nu=0); 
end; 
 
long double Bessel(long double n, long double x); 
{ 
	int nn = n; 
	if (nn == n)  
		return Besseln(n, x); 
	else  
		return Bessela(n, x); 
} 
 
*/ 
 
long double ArSinhl(long double x) 
{ 
	if (x < 0) return -logl(-x+sqrtl(sqrl(-x)+1)); 
	return logl(x+sqrtl(sqrl(x)+1)); 
} 
 
long double ArCoshl(long double x) 
{ 
	return logl(x+sqrtl(sqrl(x)-1)); 
} 
 
long double ArTanhl(long double x) 
{ 
	return 0.5L*logl((1+x)/(1-x)); 
} 
 
long double ArCothl(long double x) 
{ 
	return 0.5L*logl((x+1)/(x-1)); 
} 
 
double ArSinh(double x) 
{ 
	if (x < 0) return -log(-x+sqrt(sqr(-x)+1)); 
	return log(x+sqrt(sqr(x)+1)); 
} 
 
double ArCosh(double x) 
{ 
	return log(x+sqrt(sqr(x)-1)); 
} 
 
double ArTanh(double x) 
{ 
	return 0.5*logl((1+x)/(1-x)); 
} 
 
double ArCoth(double x) 
{ 
	return 0.5*log((x+1)/(x-1)); 
}