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