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