CLHEP 2.4.6.4
C++ Class Library for High Energy Physics
Loading...
Searching...
No Matches
RandGaussQ.cc
Go to the documentation of this file.
1//
2// -*- C++ -*-
3//
4// -----------------------------------------------------------------------
5// HEP Random
6// --- RandGaussQ ---
7// class implementation file
8// -----------------------------------------------------------------------
9
10// =======================================================================
11// M Fischler - Created 24 Jan 2000
12// M Fischler - put and get to/from streams 12/13/04
13// =======================================================================
14
15#include "CLHEP/Random/defs.h"
16#include "CLHEP/Random/RandGaussQ.h"
17#include "CLHEP/Units/PhysicalConstants.h"
18#include <iostream>
19#include <cmath> // for std::log()
20
21namespace CLHEP {
22
23std::string RandGaussQ::name() const {return "RandGaussQ";}
25
27}
28
31}
32
33double RandGaussQ::operator()( double mean, double stdDev ) {
34 return transformQuick(localEngine->flat()) * stdDev + mean;
35}
36
37void RandGaussQ::shootArray( const int size, double* vect,
38 double mean, double stdDev )
39{
40 for( double* v = vect; v != vect + size; ++v )
41 *v = shoot(mean,stdDev);
42}
43
45 const int size, double* vect,
46 double mean, double stdDev )
47{
48 for( double* v = vect; v != vect + size; ++v )
49 *v = shoot(anEngine,mean,stdDev);
50}
51
52void RandGaussQ::fireArray( const int size, double* vect)
53{
54 for( double* v = vect; v != vect + size; ++v )
56}
57
58void RandGaussQ::fireArray( const int size, double* vect,
59 double mean, double stdDev )
60{
61 for( double* v = vect; v != vect + size; ++v )
62 *v = fire( mean, stdDev );
63}
64
65//
66// Table of errInts, for use with transform(r) and quickTransform(r)
67//
68
69// Since all these are this is static to this compilation unit only, the
70// info is establised a priori and not at each invocation.
71
72// The main data is of course the gaussQTables table; the rest is all
73// bookkeeping to know what the tables mean.
74
75#define Table0size 250
76#define Table1size 1000
77#define TableSize (Table0size+Table1size)
78
79#define Table0step (2.0E-6)
80#define Table1step (5.0E-4)
81
82#define Table0scale (1.0/Table1step)
83
84#define Table0offset 0
85#define Table1offset (Table0size)
86
87 // Here comes the big (5K bytes) table, kept in a file ---
88
89static const float gaussTables [TableSize] = {
90#include "gaussQTables.cdat"
91};
92
93double RandGaussQ::transformQuick (double r) {
94 double sign = +1.0; // We always compute a negative number of
95 // sigmas. For r > 0 we will multiply by
96 // sign = -1 to return a positive number.
97 if ( r > .5 ) {
98 r = 1-r;
99 sign = -1.0;
100 }
101
102 int index;
103 double dx;
104
105 if ( r >= Table1step ) {
106 index = int((Table1size<<1) * r); // 1 to Table1size
107 if (index == Table1size) return 0.0;
108 dx = (Table1size<<1) * r - index; // fraction of way to next bin
109 index += Table1offset-1;
110 } else if ( r > Table0step ) {
111 double rr = r * Table0scale;
112 index = int(Table0size * rr); // 1 to Table0size
113 dx = Table0size * rr - index; // fraction of way to next bin
114 index += Table0offset-1;
115 } else { // r <= Table0step - not in tables
116 return sign*transformSmall(r);
117 }
118
119 double y0 = gaussTables [index++];
120 double y1 = gaussTables [index];
121
122 return (float) (sign * ( y1 * dx + y0 * (1.0-dx) ));
123
124} // transformQuick()
125
126double RandGaussQ::transformSmall (double r) {
127
128 // Solve for -v in the asymtotic formula
129 //
130 // errInt (-v) = exp(-v*v/2) 1 1*3 1*3*5
131 // ------------ * (1 - ---- + ---- - ----- + ... )
132 // v*sqrt(2*pi) v**2 v**4 v**6
133
134 // The value of r (=errInt(-v)) supplied is going to less than 2.0E-13,
135 // which is such that v < -7.25. Since the value of r is meaningful only
136 // to an absolute error of 1E-16 (double precision accuracy for a number
137 // which on the high side could be of the form 1-epsilon), computing
138 // v to more than 3-4 digits of accuracy is suspect; however, to ensure
139 // smoothness with the table generator (which uses quite a few terms) we
140 // also use terms up to 1*3*5* ... *13/v**14, and insist on accuracy of
141 // solution at the level of 1.0e-7.
142
143 // This routine is called less than one time in a million firings, so
144 // speed is of no concern. As a matter of technique, we terminate the
145 // iterations in case they would be infinite, but this should not happen.
146
147 double eps = 1.0e-7;
148 double guess = 7.5;
149 double v;
150
151 for ( int i = 1; i < 50; i++ ) {
152 double vn2 = 1.0/(guess*guess);
153 double s1 = -13*11*9*7*5*3 * vn2*vn2*vn2*vn2*vn2*vn2*vn2;
154 s1 += 11*9*7*5*3 * vn2*vn2*vn2*vn2*vn2*vn2;
155 s1 += -9*7*5*3 * vn2*vn2*vn2*vn2*vn2;
156 s1 += 7*5*3 * vn2*vn2*vn2*vn2;
157 s1 += -5*3 * vn2*vn2*vn2;
158 s1 += 3 * vn2*vn2 - vn2 + 1.0;
159 v = std::sqrt ( 2.0 * std::log ( s1 / (r*guess*std::sqrt(CLHEP::twopi)) ) );
160 if ( std::fabs(v-guess) < eps ) break;
161 guess = v;
162 }
163 return -v;
164
165} // transformSmall()
166
167std::ostream & RandGaussQ::put ( std::ostream & os ) const {
168 long pr=os.precision(20);
169 os << " " << name() << "\n";
170 RandGauss::put(os);
171 os.precision(pr);
172 return os;
173}
174
175std::istream & RandGaussQ::get ( std::istream & is ) {
176 std::string inName;
177 is >> inName;
178 if (inName != name()) {
179 is.clear(std::ios::badbit | is.rdstate());
180 std::cerr << "Mismatch when expecting to read state of a "
181 << name() << " distribution\n"
182 << "Name found was " << inName
183 << "\nistream is left in the badbit state\n";
184 return is;
185 }
186 RandGauss::get(is);
187 return is;
188}
189
190} // namespace CLHEP
#define Table0scale
Definition: RandGaussQ.cc:82
static double shoot()
virtual ~RandGaussQ()
Definition: RandGaussQ.cc:26
std::istream & get(std::istream &is)
Definition: RandGaussQ.cc:175
static double transformSmall(double r)
Definition: RandGaussQ.cc:126
std::ostream & put(std::ostream &os) const
Definition: RandGaussQ.cc:167
static void shootArray(const int size, double *vect, double mean=0.0, double stdDev=1.0)
Definition: RandGaussQ.cc:37
void fireArray(const int size, double *vect)
Definition: RandGaussQ.cc:52
HepRandomEngine & engine()
Definition: RandGaussQ.cc:24
std::string name() const
Definition: RandGaussQ.cc:23
virtual double operator()()
Definition: RandGaussQ.cc:29
static double transformQuick(double r)
Definition: RandGaussQ.cc:93
std::istream & get(std::istream &is)
Definition: RandGauss.cc:285
double defaultStdDev
Definition: RandGauss.h:154
std::ostream & put(std::ostream &os) const
Definition: RandGauss.cc:260
HepRandomEngine & engine()
Definition: RandGauss.cc:47
double defaultMean
Definition: RandGauss.h:153
std::shared_ptr< HepRandomEngine > localEngine
Definition: RandGauss.h:156
#define Table1offset
#define Table0step
#define TableSize
#define Table0offset
#define Table0size
#define Table1step
#define Table1size