Alex Bikfalvi
SimStream Documentation
Hyp.cpp
00001 #include "Headers.h" 00002 #include "Hyp.h" 00003 #include "Gamma.h" 00004 00005 #define PRECISION 1E-16 00006 #define ROUND(x) ((x >= 0)?floor(x+0.5):ceil(x-0.5)) 00007 00008 double Hypergeometric2F1Series(double a, double b, double c, double z) 00009 { 00010 unsigned int i = 1; 00011 double term = a*b*z/c; 00012 double sum = 1+term; 00013 00014 do 00015 { 00016 term *= ((a+i)*(b+i)*z)/((c+i)*(i+1)); 00017 sum += term; 00018 i++; 00019 } 00020 while(fabs(term) > PRECISION); 00021 return sum; 00022 } 00023 00024 double Hypergeometric2F1(double a, double b, double c, double z) 00025 { 00026 // double delta = 0.051776695296636881100211090526; 00027 00028 if(fabs(z) < PRECISION) return 1; // z = 0; 00029 else if(fabs(z-1) < PRECISION) // z = 1; 00030 { 00031 if(fabs(c-a-b) < PRECISION) return 1E300; 00032 else return Gamma(c)*Gamma(c-a-b)/(Gamma(c-a)*Gamma(c-b)); 00033 } 00034 00035 if(z < -1) 00036 { 00037 double w = 1/(1-z); 00038 return pow(w,a) * Hypergeometric2F1Series(a,c-b,a-b+1,w) * exp(LnGamma(c) + LnGamma(b-a) - LnGamma(b) - LnGamma(c-a)) + 00039 pow(w,b) * Hypergeometric2F1Series(b,c-a,b-a+1,w) * exp(LnGamma(c) + LnGamma(a-b) - LnGamma(a) - LnGamma(c-b)); 00040 } 00041 else if(z < 0) 00042 { 00043 double w = z/(z-1); 00044 return pow(1-w,a) * Hypergeometric2F1Series(a,c-b,c,w); 00045 } 00046 else if(z <= 0.5) 00047 { 00048 return Hypergeometric2F1Series(a,b,c,z); 00049 } 00050 else if(z <= 1) 00051 { 00052 double w = 1-z; 00053 return Hypergeometric2F1Series(a,b,a+b-c+1,w) * exp(LnGamma(c) + LnGamma(c-a-b) - LnGamma(c-a) - LnGamma(c-b)) + 00054 pow(w,c-a-b) * Hypergeometric2F1Series(c-a,c-b,c-a-b+1,w) * exp(LnGamma(c) + LnGamma(a+b-c) - LnGamma(a) - LnGamma(b)); 00055 } 00056 else if(z <= 2) 00057 { 00058 double w = 1 - (1/z); 00059 double re = pow(1-w,a) * Hypergeometric2F1Series(a,a-c+1,a+b-c+1,w) * exp(LnGamma(c) + LnGamma(c-a-b) - LnGamma(c-a) - LnGamma(c-b)) + 00060 pow(1-w,a) * pow(w,c-a-b) * cos(M_PI*(c-a-b)) * Hypergeometric2F1Series(1-b,c-b,c-a-b+1,w) * exp(LnGamma(c) + LnGamma(a+b-c) - LnGamma(a) - LnGamma(b)); 00061 //double im = -pow(1-w,a) * pow(w,c-a-b) * sin(M_PI*(c-a-b)) * Hypergeometric2F1Series(c-a,1-a,c-a-b+1,w) * exp(LnGamma(c) + LnGamma(a+b-c) - LnGamma(a) - LnGamma(b)); 00062 return re; 00063 } 00064 else 00065 { 00066 double w = 1/z; 00067 double re = pow(w,a) * cos(M_PI*a) * Hypergeometric2F1Series(a,a-c+1,a-b+1,w) * exp(LnGamma(c) + LnGamma(b-a) - LnGamma(b) - LnGamma(c-a)) + 00068 pow(w,b) * cos(M_PI*b) * Hypergeometric2F1Series(b-c+1,b,b-a+1,w) * exp(LnGamma(c) + LnGamma(a-b) - LnGamma(a) - LnGamma(c-b)); 00069 //double im = pow(w,a) * sin(M_PI*a) * Hypergeometric2F1Series(a,a-c+1,a-b+1,w) * exp(LnGamma(c) + LnGamma(b-a) - LnGamma(b) - LnGamma(c-a)) + 00070 // pow(w,b) * sin(M_PI*b) * Hypergeometric2F1Series(b-c+1,b,b-a+1,w) * exp(LnGamma(c) + LnGamma(a-b) - LnGamma(a) - LnGamma(c-b)); 00071 return re; 00072 } 00073 } 00074 00075 Hyp2F1::Hyp2F1(double a, double b, double c) 00076 { 00077 this->a = a; 00078 this->b = b; 00079 this->c = c; 00080 00081 this->c1 = fabs(c-a-b); 00082 this->c2 = Gamma(c)*Gamma(c-a-b)/(Gamma(c-a)*Gamma(c-b)); 00083 this->c3 = exp(LnGamma(c) + LnGamma(b-a) - LnGamma(b) - LnGamma(c-a)); 00084 this->c4 = exp(LnGamma(c) + LnGamma(a-b) - LnGamma(a) - LnGamma(c-b)); 00085 this->c5 = exp(LnGamma(c) + LnGamma(c-a-b) - LnGamma(c-a) - LnGamma(c-b)); 00086 this->c6 = exp(LnGamma(c) + LnGamma(a+b-c) - LnGamma(a) - LnGamma(b)); 00087 this->c7 = cos(M_PI*(c-a-b)); 00088 this->c8 = sin(M_PI*(c-a-b)); 00089 this->c9 = cos(M_PI*a); 00090 this->c10 = cos(M_PI*b); 00091 this->c11 = sin(M_PI*a); 00092 this->c12 = sin(M_PI*b); 00093 } 00094 00095 double Hyp2F1::operator()(double z) 00096 { 00097 if(fabs(z) < PRECISION) return 1; // z = 0; 00098 else if(fabs(z-1) < PRECISION) // z = 1; 00099 { 00100 if(this->c1 < PRECISION) return 1E300; 00101 else return this->c2; 00102 } 00103 00104 if(z < -1) 00105 { 00106 double w = 1/(1-z); 00107 return pow(w,a) * Hypergeometric2F1Series(a,c-b,a-b+1,w) * this->c3 + 00108 pow(w,b) * Hypergeometric2F1Series(b,c-a,b-a+1,w) * this->c4; 00109 } 00110 else if(z < 0) 00111 { 00112 double w = z/(z-1); 00113 return pow(1-w,a) * Hypergeometric2F1Series(a,c-b,c,w); 00114 } 00115 else if(z <= 0.5) 00116 { 00117 return Hypergeometric2F1Series(a,b,c,z); 00118 } 00119 else if(z <= 1) 00120 { 00121 double w = 1-z; 00122 return Hypergeometric2F1Series(a,b,a+b-c+1,w) * this->c5 + 00123 pow(w,c-a-b) * Hypergeometric2F1Series(c-a,c-b,c-a-b+1,w) * this->c6; 00124 } 00125 else if(z <= 2) 00126 { 00127 double w = 1 - (1/z); 00128 double re = pow(1-w,a) * Hypergeometric2F1Series(a,a-c+1,a+b-c+1,w) * this->c5 + 00129 pow(1-w,a) * pow(w,c-a-b) * this->c7 * Hypergeometric2F1Series(1-b,c-b,c-a-b+1,w) * this->c6; 00130 //double im = -pow(1-w,a) * pow(w,c-a-b) * this->c8 * Hypergeometric2F1Series(c-a,1-a,c-a-b+1,w) * this->c6; 00131 return re; 00132 } 00133 else 00134 { 00135 double w = 1/z; 00136 00137 double h1 = pow(w,a) * Hypergeometric2F1Series(a,a-c+1,a-b+1,w) * this->c3; 00138 double h2 = pow(w,b) * Hypergeometric2F1Series(b-c+1,b,b-a+1,w) * this->c4; 00139 00140 double re = this->c9 * h1 + this->c10 * h2; 00141 //double im = this->c11 * h1 + this->c12 * h2; 00142 00143 return re; 00144 } 00145 }
Last updated: February 8, 2011