CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
RandChiSquare.cc
Go to the documentation of this file.
1//
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
18#include "CLHEP/Random/defs.h"
19#include "CLHEP/Random/RandChiSquare.h"
20#include "CLHEP/Random/DoubConv.h"
21#include "CLHEP/Utility/thread_local.h"
22#include <cmath> // for std::log()
23#include <iostream>
24#include <string>
25#include <vector>
26
27namespace CLHEP {
28
29std::string RandChiSquare::name() const {return "RandChiSquare";}
30HepRandomEngine & RandChiSquare::engine() {return *localEngine;}
31
33}
34
35double RandChiSquare::shoot( HepRandomEngine *anEngine, double a ) {
36 return genChiSquare( anEngine, a );
37}
38
39double RandChiSquare::shoot( double a ) {
41 return genChiSquare( anEngine, a );
42}
43
44double RandChiSquare::fire( double a ) {
45 return genChiSquare( localEngine.get(), a );
46}
47
48void RandChiSquare::shootArray( const int size, double* vect,
49 double a ) {
50 for( double* v = vect; v != vect+size; ++v )
51 *v = shoot(a);
52}
53
55 const int size, double* vect,
56 double a )
57{
58 for( double* v = vect; v != vect+size; ++v )
59 *v = shoot(anEngine,a);
60}
61
62void RandChiSquare::fireArray( const int size, double* vect) {
63 for( double* v = vect; v != vect+size; ++v )
64 *v = fire(defaultA);
65}
66
67void RandChiSquare::fireArray( const int size, double* vect,
68 double a ) {
69 for( double* v = vect; v != vect+size; ++v )
70 *v = fire(a);
71}
72
73double RandChiSquare::genChiSquare( HepRandomEngine *anEngine,
74 double a ) {
75/******************************************************************
76 * *
77 * Chi Distribution - Ratio of Uniforms with shift *
78 * *
79 ******************************************************************
80 * *
81 * FUNCTION : - chru samples a random number from the Chi *
82 * distribution with parameter a > 1. *
83 * REFERENCE : - J.F. Monahan (1987): An algorithm for *
84 * generating chi random variables, ACM Trans. *
85 * Math. Software 13, 168-172. *
86 * SUBPROGRAM : - anEngine ... pointer to a (0,1)-Uniform *
87 * engine *
88 * *
89 * Implemented by R. Kremer, 1990 *
90 ******************************************************************/
91
92 static CLHEP_THREAD_LOCAL double a_in = -1.0,b,vm,vp,vd;
93 double u,v,z,zz,r;
94
95// Check for invalid input value
96
97 if( a < 1 ) return (-1.0);
98
99 if (a == 1)
100 {
101 for(;;)
102 {
103 u = anEngine->flat();
104 v = anEngine->flat() * 0.857763884960707;
105 z = v / u;
106 if (z < 0) continue;
107 zz = z * z;
108 r = 2.5 - zz;
109 if (z < 0.0) r = r + zz * z / (3.0 * z);
110 if (u < r * 0.3894003915) return(z*z);
111 if (zz > (1.036961043 / u + 1.4)) continue;
112 if (2 * std::log(u) < (- zz * 0.5 )) return(z*z);
113 }
114 }
115 else
116 {
117 if (a != a_in)
118 {
119 b = std::sqrt(a - 1.0);
120 vm = - 0.6065306597 * (1.0 - 0.25 / (b * b + 1.0));
121 vm = (-b > vm)? -b : vm;
122 vp = 0.6065306597 * (0.7071067812 + b) / (0.5 + b);
123 vd = vp - vm;
124 a_in = a;
125 }
126 for(;;)
127 {
128 u = anEngine->flat();
129 v = anEngine->flat() * vd + vm;
130 z = v / u;
131 if (z < -b) continue;
132 zz = z * z;
133 r = 2.5 - zz;
134 if (z < 0.0) r = r + zz * z / (3.0 * (z + b));
135 if (u < r * 0.3894003915) return((z + b)*(z + b));
136 if (zz > (1.036961043 / u + 1.4)) continue;
137 if (2 * std::log(u) < (std::log(1.0 + z / b) * b * b - zz * 0.5 - z * b)) return((z + b)*(z + b));
138 }
139 }
140}
141
142std::ostream & RandChiSquare::put ( std::ostream & os ) const {
143 long pr=os.precision(20);
144 std::vector<unsigned long> t(2);
145 os << " " << name() << "\n";
146 os << "Uvec" << "\n";
147 t = DoubConv::dto2longs(defaultA);
148 os << defaultA << " " << t[0] << " " << t[1] << "\n";
149 os.precision(pr);
150 return os;
151#ifdef REMOVED
152 long pr=os.precision(20);
153 os << " " << name() << "\n";
154 os << defaultA << "\n";
155 os.precision(pr);
156 return os;
157#endif
158}
159
160std::istream & RandChiSquare::get ( std::istream & is ) {
161 std::string inName;
162 is >> inName;
163 if (inName != name()) {
164 is.clear(std::ios::badbit | is.rdstate());
165 std::cerr << "Mismatch when expecting to read state of a "
166 << name() << " distribution\n"
167 << "Name found was " << inName
168 << "\nistream is left in the badbit state\n";
169 return is;
170 }
171 if (possibleKeywordInput(is, "Uvec", defaultA)) {
172 std::vector<unsigned long> t(2);
173 is >> defaultA >> t[0] >> t[1]; defaultA = DoubConv::longs2double(t);
174 return is;
175 }
176 // is >> defaultA encompassed by possibleKeywordInput
177 return is;
178}
179
180
181
182} // namespace CLHEP
183
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:270
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
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:168