Geant4 Cross Reference |
1 // 2 // ******************************************************************** 3 // * License and Disclaimer * 4 // * * 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. * 10 // * * 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitation of liability. * 17 // * * 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************************************** 25 // 26 // 27 // 28 // ------------------------------------------------------------ 29 // GEANT 4 class implementation 30 // ------------------------------------------------------------ 31 32 #include <cmath> 33 #include <string.h> 34 #include "Gamma.hh" 35 36 MyGamma::MyGamma(){} 37 38 MyGamma::~MyGamma(){} 39 40 //____________________________________________________________________________ 41 double MyGamma::Gamma(double z) 42 { 43 if (z <= 0) 44 return 0; 45 46 return std::tgamma(z); 47 } 48 49 //____________________________________________________________________________ 50 double MyGamma::Gamma(double a, double x) 51 { 52 // Computation of the incomplete gamma function P(a,x) 53 // 54 // The algorithm is based on the formulas and code as denoted in 55 // Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.). 56 // 57 //--- Nve 14-nov-1998 UU-SAP Utrecht 58 59 if (a <= 0 || x <= 0) return 0; 60 61 if (x < (a + 1)) 62 return GamSer(a, x); 63 else 64 return GamCf(a, x); 65 } 66 67 //____________________________________________________________________________ 68 double MyGamma::GamCf(double a, double x) 69 { 70 // Computation of the incomplete gamma function P(a,x) 71 // via its continued fraction representation. 72 // 73 // The algorithm is based on the formulas and code as denoted in 74 // Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.). 75 // 76 //--- Nve 14-nov-1998 UU-SAP Utrecht 77 78 int itmax = 100; // Maximum number of iterations 79 double eps = 3.e-7; // Relative accuracy 80 double fpmin = 1.e-30; // Smallest double value allowed here 81 82 if (a <= 0 || x <= 0) return 0; 83 84 double gln = LnGamma(a); 85 double b = x + 1 - a; 86 double c = 1 / fpmin; 87 double d = 1 / b; 88 double h = d; 89 double an, del; 90 for (int i = 1; i <= itmax; i++) { 91 an = double(-i) * (double(i) - a); 92 b += 2; 93 d = an * d + b; 94 if (Abs(d) < fpmin) d = fpmin; 95 c = b + an / c; 96 if (Abs(c) < fpmin) c = fpmin; 97 d = 1 / d; 98 del = d * c; 99 h = h * del; 100 if (Abs(del - 1) < eps) break; 101 // if (i==itmax) cout << "*GamCf(a,x)* a too large or itmax too small" << endl; 102 } 103 double v = Exp(-x + a * Log(x) - gln) * h; 104 return (1 - v); 105 } 106 107 //____________________________________________________________________________ 108 double MyGamma::GamSer(double a, double x) 109 { 110 // Computation of the incomplete gamma function P(a,x) 111 // via its series representation. 112 // 113 // The algorithm is based on the formulas and code as denoted in 114 // Numerical Recipes 2nd ed. on p. 210-212 (W.H.Press et al.). 115 // 116 //--- Nve 14-nov-1998 UU-SAP Utrecht 117 118 int itmax = 100; // Maximum number of iterations 119 double eps = 3.e-7; // Relative accuracy 120 121 if (a <= 0 || x <= 0) return 0; 122 123 double gln = LnGamma(a); 124 double ap = a; 125 double sum = 1 / a; 126 double del = sum; 127 for (int n = 1; n <= itmax; n++) { 128 ap += 1; 129 del = del * x / ap; 130 sum += del; 131 if (MyGamma::Abs(del) < Abs(sum * eps)) break; 132 // if (n==itmax) cout << "*GamSer(a,x)* a too large or itmax too small" << endl; 133 } 134 double v = sum * Exp(-x + a * Log(x) - gln); 135 return v; 136 } 137 138 double MyGamma::LnGamma(double z) 139 { 140 if (z <= 0) 141 return 0; 142 143 return std::lgamma(z); 144 } 145