Geant4 Cross Reference |
1 // -*- C++ -*- 1 // -*- C++ -*- 2 // 2 // 3 // ------------------------------------------- 3 // ----------------------------------------------------------------------- 4 // HEP Random 4 // HEP Random 5 // --- RandChiSquare 5 // --- RandChiSquare --- 6 // class implementation f 6 // class implementation file 7 // ------------------------------------------- 7 // ----------------------------------------------------------------------- 8 8 9 // =========================================== 9 // ======================================================================= 10 // John Marraffino - Created: 12th May 1998 10 // John Marraffino - Created: 12th May 1998 11 // M Fischler - put and get to/from stream 11 // M Fischler - put and get to/from streams 12/10/04 12 // M Fischler - put/get to/from streams 12 // M Fischler - put/get to/from streams uses pairs of ulongs when 13 // + storing doubles avoid problems with 13 // + storing doubles avoid problems with precision 14 // 4/14/05 14 // 4/14/05 15 // =========================================== 15 // ======================================================================= 16 16 17 #include "CLHEP/Random/RandChiSquare.h" 17 #include "CLHEP/Random/RandChiSquare.h" 18 #include "CLHEP/Random/DoubConv.h" 18 #include "CLHEP/Random/DoubConv.h" 19 #include "CLHEP/Utility/thread_local.h" 19 #include "CLHEP/Utility/thread_local.h" 20 #include <cmath> // for std::log() 20 #include <cmath> // for std::log() 21 #include <iostream> 21 #include <iostream> 22 #include <string> 22 #include <string> 23 #include <vector> 23 #include <vector> 24 24 25 namespace CLHEP { 25 namespace CLHEP { 26 26 27 std::string RandChiSquare::name() const {retur 27 std::string RandChiSquare::name() const {return "RandChiSquare";} 28 HepRandomEngine & RandChiSquare::engine() {ret 28 HepRandomEngine & RandChiSquare::engine() {return *localEngine;} 29 29 30 RandChiSquare::~RandChiSquare() { 30 RandChiSquare::~RandChiSquare() { 31 } 31 } 32 32 33 double RandChiSquare::shoot( HepRandomEngine * 33 double RandChiSquare::shoot( HepRandomEngine *anEngine, double a ) { 34 return genChiSquare( anEngine, a ); 34 return genChiSquare( anEngine, a ); 35 } 35 } 36 36 37 double RandChiSquare::shoot( double a ) { 37 double RandChiSquare::shoot( double a ) { 38 HepRandomEngine *anEngine = HepRandom::getTh 38 HepRandomEngine *anEngine = HepRandom::getTheEngine(); 39 return genChiSquare( anEngine, a ); 39 return genChiSquare( anEngine, a ); 40 } 40 } 41 41 42 double RandChiSquare::fire( double a ) { 42 double RandChiSquare::fire( double a ) { 43 return genChiSquare( localEngine.get(), a ); 43 return genChiSquare( localEngine.get(), a ); 44 } 44 } 45 45 46 void RandChiSquare::shootArray( const int size 46 void RandChiSquare::shootArray( const int size, double* vect, 47 double a ) { 47 double a ) { 48 for( double* v = vect; v != vect+size; ++v ) 48 for( double* v = vect; v != vect+size; ++v ) 49 *v = shoot(a); 49 *v = shoot(a); 50 } 50 } 51 51 52 void RandChiSquare::shootArray( HepRandomEngin 52 void RandChiSquare::shootArray( HepRandomEngine* anEngine, 53 const int size, do 53 const int size, double* vect, 54 double a ) 54 double a ) 55 { 55 { 56 for( double* v = vect; v != vect+size; ++v ) 56 for( double* v = vect; v != vect+size; ++v ) 57 *v = shoot(anEngine,a); 57 *v = shoot(anEngine,a); 58 } 58 } 59 59 60 void RandChiSquare::fireArray( const int size, 60 void RandChiSquare::fireArray( const int size, double* vect) { 61 for( double* v = vect; v != vect+size; ++v ) 61 for( double* v = vect; v != vect+size; ++v ) 62 *v = fire(defaultA); 62 *v = fire(defaultA); 63 } 63 } 64 64 65 void RandChiSquare::fireArray( const int size, 65 void RandChiSquare::fireArray( const int size, double* vect, 66 double a ) { 66 double a ) { 67 for( double* v = vect; v != vect+size; ++v ) 67 for( double* v = vect; v != vect+size; ++v ) 68 *v = fire(a); 68 *v = fire(a); 69 } 69 } 70 70 71 double RandChiSquare::genChiSquare( HepRandomE 71 double RandChiSquare::genChiSquare( HepRandomEngine *anEngine, 72 double 72 double a ) { 73 /********************************************* 73 /****************************************************************** 74 * 74 * * 75 * Chi Distribution - Ratio of Uniforms 75 * Chi Distribution - Ratio of Uniforms with shift * 76 * 76 * * 77 ********************************************* 77 ****************************************************************** 78 * 78 * * 79 * FUNCTION : - chru samples a random number 79 * FUNCTION : - chru samples a random number from the Chi * 80 * distribution with parameter 80 * distribution with parameter a > 1. * 81 * REFERENCE : - J.F. Monahan (1987): An algo 81 * REFERENCE : - J.F. Monahan (1987): An algorithm for * 82 * generating chi random variab 82 * generating chi random variables, ACM Trans. * 83 * Math. Software 13, 168-172. 83 * Math. Software 13, 168-172. * 84 * SUBPROGRAM : - anEngine ... pointer to a ( 84 * SUBPROGRAM : - anEngine ... pointer to a (0,1)-Uniform * 85 * engine 85 * engine * 86 * 86 * * 87 * Implemented by R. Kremer, 1990 87 * Implemented by R. Kremer, 1990 * 88 ********************************************* 88 ******************************************************************/ 89 89 90 static CLHEP_THREAD_LOCAL double a_in = -1.0, 90 static CLHEP_THREAD_LOCAL double a_in = -1.0,b,vm,vp,vd; 91 double u,v,z,zz,r; 91 double u,v,z,zz,r; 92 92 93 // Check for invalid input value 93 // Check for invalid input value 94 94 95 if( a < 1 ) return (-1.0); 95 if( a < 1 ) return (-1.0); 96 96 97 if (a == 1) 97 if (a == 1) 98 { 98 { 99 for(;;) 99 for(;;) 100 { 100 { 101 u = anEngine->flat(); 101 u = anEngine->flat(); 102 v = anEngine->flat() * 0.857763884960707; 102 v = anEngine->flat() * 0.857763884960707; 103 z = v / u; 103 z = v / u; 104 if (z < 0) continue; 104 if (z < 0) continue; 105 zz = z * z; 105 zz = z * z; 106 r = 2.5 - zz; 106 r = 2.5 - zz; 107 if (z < 0.0) r = r + zz * z / (3.0 * z); 107 if (z < 0.0) r = r + zz * z / (3.0 * z); 108 if (u < r * 0.3894003915) return(z*z); 108 if (u < r * 0.3894003915) return(z*z); 109 if (zz > (1.036961043 / u + 1.4)) continu 109 if (zz > (1.036961043 / u + 1.4)) continue; 110 if (2 * std::log(u) < (- zz * 0.5 )) retu 110 if (2 * std::log(u) < (- zz * 0.5 )) return(z*z); 111 } 111 } 112 } 112 } 113 else 113 else 114 { 114 { 115 if (a != a_in) 115 if (a != a_in) 116 { 116 { 117 b = std::sqrt(a - 1.0); 117 b = std::sqrt(a - 1.0); 118 vm = - 0.6065306597 * (1.0 - 0.25 / (b * 118 vm = - 0.6065306597 * (1.0 - 0.25 / (b * b + 1.0)); 119 vm = (-b > vm)? -b : vm; 119 vm = (-b > vm)? -b : vm; 120 vp = 0.6065306597 * (0.7071067812 + b) / 120 vp = 0.6065306597 * (0.7071067812 + b) / (0.5 + b); 121 vd = vp - vm; 121 vd = vp - vm; 122 a_in = a; 122 a_in = a; 123 } 123 } 124 for(;;) 124 for(;;) 125 { 125 { 126 u = anEngine->flat(); 126 u = anEngine->flat(); 127 v = anEngine->flat() * vd + vm; 127 v = anEngine->flat() * vd + vm; 128 z = v / u; 128 z = v / u; 129 if (z < -b) continue; 129 if (z < -b) continue; 130 zz = z * z; 130 zz = z * z; 131 r = 2.5 - zz; 131 r = 2.5 - zz; 132 if (z < 0.0) r = r + zz * z / (3.0 * (z + 132 if (z < 0.0) r = r + zz * z / (3.0 * (z + b)); 133 if (u < r * 0.3894003915) return((z + b)* 133 if (u < r * 0.3894003915) return((z + b)*(z + b)); 134 if (zz > (1.036961043 / u + 1.4)) continu 134 if (zz > (1.036961043 / u + 1.4)) continue; 135 if (2 * std::log(u) < (std::log(1.0 + z / 135 if (2 * std::log(u) < (std::log(1.0 + z / b) * b * b - zz * 0.5 - z * b)) return((z + b)*(z + b)); 136 } 136 } 137 } 137 } 138 } 138 } 139 139 140 std::ostream & RandChiSquare::put ( std::ostre 140 std::ostream & RandChiSquare::put ( std::ostream & os ) const { 141 long pr=os.precision(20); 141 long pr=os.precision(20); 142 std::vector<unsigned long> t(2); 142 std::vector<unsigned long> t(2); 143 os << " " << name() << "\n"; 143 os << " " << name() << "\n"; 144 os << "Uvec" << "\n"; 144 os << "Uvec" << "\n"; 145 t = DoubConv::dto2longs(defaultA); 145 t = DoubConv::dto2longs(defaultA); 146 os << defaultA << " " << t[0] << " " << t[1] 146 os << defaultA << " " << t[0] << " " << t[1] << "\n"; 147 os.precision(pr); 147 os.precision(pr); 148 return os; 148 return os; 149 } 149 } 150 150 151 std::istream & RandChiSquare::get ( std::istre 151 std::istream & RandChiSquare::get ( std::istream & is ) { 152 std::string inName; 152 std::string inName; 153 is >> inName; 153 is >> inName; 154 if (inName != name()) { 154 if (inName != name()) { 155 is.clear(std::ios::badbit | is.rdstate()); 155 is.clear(std::ios::badbit | is.rdstate()); 156 std::cerr << "Mismatch when expecting to r 156 std::cerr << "Mismatch when expecting to read state of a " 157 << name() << " distribution\n" 157 << name() << " distribution\n" 158 << "Name found was " << inName 158 << "Name found was " << inName 159 << "\nistream is left in the badbit st 159 << "\nistream is left in the badbit state\n"; 160 return is; 160 return is; 161 } 161 } 162 if (possibleKeywordInput(is, "Uvec", default 162 if (possibleKeywordInput(is, "Uvec", defaultA)) { 163 std::vector<unsigned long> t(2); 163 std::vector<unsigned long> t(2); 164 is >> defaultA >> t[0] >> t[1]; defaultA = 164 is >> defaultA >> t[0] >> t[1]; defaultA = DoubConv::longs2double(t); 165 return is; 165 return is; 166 } 166 } 167 // is >> defaultA encompassed by possibleKey 167 // is >> defaultA encompassed by possibleKeywordInput 168 return is; 168 return is; 169 } 169 } 170 170 171 171 172 172 173 } // namespace CLHEP 173 } // namespace CLHEP 174 174 175 175