Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/RandGeneral.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /externals/clhep/src/RandGeneral.cc (Version 11.3.0) and /externals/clhep/src/RandGeneral.cc (Version 10.7.p2)


  1 // -*- C++ -*-                                      1 // -*- C++ -*-
  2 //                                                  2 //
  3 // -------------------------------------------      3 // -----------------------------------------------------------------------
  4 //                             HEP Random           4 //                             HEP Random
  5 //                          --- RandGeneral --      5 //                          --- RandGeneral ---
  6 //                      class implementation f      6 //                      class implementation file
  7 // -------------------------------------------      7 // -----------------------------------------------------------------------
  8                                                     8 
  9 // ===========================================      9 // =======================================================================
 10 // S.Magni & G.Pieri - Created: 5th September      10 // S.Magni & G.Pieri - Created: 5th September 1995
 11 // G.Cosmo           - Added constructor using     11 // G.Cosmo           - Added constructor using default engine from the
 12 //                     static generator. Simpl     12 //                     static generator. Simplified shoot() and
 13 //                     shootArray() (not neede     13 //                     shootArray() (not needed in principle!): 20th Aug 1998
 14 // M.G.Pia & G.Cosmo - Fixed bug in computatio     14 // M.G.Pia & G.Cosmo - Fixed bug in computation of theIntegralPdf in
 15 //                     two constructors: 5th J     15 //                     two constructors: 5th Jan 1999
 16 // S.Magni & G.Pieri - Added linear interpolat     16 // S.Magni & G.Pieri - Added linear interpolation: 24th Mar 1999
 17 // M. Fischler       - General cleanup: 14th M     17 // M. Fischler       - General cleanup: 14th May 1999
 18 //      + Eliminated constructor code replicat     18 //      + Eliminated constructor code replication by factoring 
 19 //        common code into prepareTable.           19 //        common code into prepareTable.
 20 //      + Eliminated fire/shoot code replicati     20 //      + Eliminated fire/shoot code replication by factoring 
 21 //        out common code into mapRandom.          21 //        out common code into mapRandom.  
 22 //      + A couple of methods are moved inline     22 //      + A couple of methods are moved inline to avoid a 
 23 //        speed cost for factoring out mapRand     23 //        speed cost for factoring out mapRandom:  fire()
 24 //        and shoot(anEngine).                     24 //        and shoot(anEngine).
 25 //      + Inserted checks for negative weight      25 //      + Inserted checks for negative weight and zero total 
 26 //        weight in the bins.                      26 //        weight in the bins.
 27 //      + Modified the binary search loop to a     27 //      + Modified the binary search loop to avoid incorrect
 28 //        behavior when rand is example on a b     28 //        behavior when rand is example on a boundary.
 29 //      + Moved the check of InterpolationType     29 //      + Moved the check of InterpolationType up into 
 30 //        the constructor.  A type other than      30 //        the constructor.  A type other than 0 or 1
 31 //        will give the interpolated distribut     31 //        will give the interpolated distribution (instead of
 32 //        a distribution that always returns 0     32 //        a distribution that always returns 0).
 33 //      + Modified the computation of the retu     33 //      + Modified the computation of the returned value
 34 //        to use algeraic simplification to im     34 //        to use algeraic simplification to improve speed.
 35 //        Eliminated two of the three division     35 //        Eliminated two of the three divisionns, made
 36 //        use of the fact that nabove-nbelow i     36 //        use of the fact that nabove-nbelow is always 1, etc.
 37 //      + Inserted a check for rand hitting th     37 //      + Inserted a check for rand hitting the boundary of a
 38 //        zero-width bin, to avoid dividing 0/     38 //        zero-width bin, to avoid dividing 0/0.  
 39 // M. Fischler        - Minor correction in as     39 // M. Fischler        - Minor correction in assert 31 July 2001
 40 //      + changed from assert (above = below+1     40 //      + changed from assert (above = below+1) to ==
 41 // M Fischler         - put and get to/from st     41 // M Fischler         - put and get to/from streams 12/15/04
 42 //      + Modifications to use a vector as the     42 //      + Modifications to use a vector as theIntegraPdf
 43 // M Fischler       - put/get to/from streams      43 // M Fischler       - put/get to/from streams uses pairs of ulongs when
 44 //      + storing doubles avoid problems with      44 //      + storing doubles avoid problems with precision 
 45 //      4/14/05                                    45 //      4/14/05
 46 //                                                 46 //
 47 // ===========================================     47 // =======================================================================
 48                                                    48 
 49 #include "CLHEP/Random/RandGeneral.h"              49 #include "CLHEP/Random/RandGeneral.h"
 50 #include "CLHEP/Random/DoubConv.h"                 50 #include "CLHEP/Random/DoubConv.h"
 51 #include <cassert>                                 51 #include <cassert>
 52 #include <iostream>                                52 #include <iostream>
 53 #include <string>                                  53 #include <string>
 54 #include <vector>                                  54 #include <vector>
 55                                                    55 
 56 namespace CLHEP {                                  56 namespace CLHEP {
 57                                                    57 
 58 std::string RandGeneral::name() const {return      58 std::string RandGeneral::name() const {return "RandGeneral";}
 59 HepRandomEngine & RandGeneral::engine() {retur     59 HepRandomEngine & RandGeneral::engine() {return *localEngine;}
 60                                                    60 
 61                                                   61 
 62 //////////////////                                 62 //////////////////
 63 // Constructors                                    63 // Constructors
 64 //////////////////                                 64 //////////////////
 65                                                    65 
 66 RandGeneral::RandGeneral( const double* aProbF     66 RandGeneral::RandGeneral( const double* aProbFunc, 
 67         int theProbSize,                           67         int theProbSize, 
 68         int IntType  )                             68         int IntType  )
 69   : HepRandom(),                                   69   : HepRandom(),
 70     localEngine(HepRandom::getTheEngine(), do_     70     localEngine(HepRandom::getTheEngine(), do_nothing_deleter()),
 71     nBins(theProbSize),                            71     nBins(theProbSize), 
 72     InterpolationType(IntType)                     72     InterpolationType(IntType)
 73 {                                                  73 {
 74   prepareTable(aProbFunc);                         74   prepareTable(aProbFunc);
 75 }                                                  75 }
 76                                                    76 
 77 RandGeneral::RandGeneral(HepRandomEngine& anEn     77 RandGeneral::RandGeneral(HepRandomEngine& anEngine,
 78                          const double* aProbFu     78                          const double* aProbFunc, 
 79        int theProbSize,                            79        int theProbSize, 
 80        int IntType  )                              80        int IntType  )
 81 : HepRandom(),                                     81 : HepRandom(),
 82   localEngine(&anEngine, do_nothing_deleter())     82   localEngine(&anEngine, do_nothing_deleter()), 
 83   nBins(theProbSize),                              83   nBins(theProbSize),
 84   InterpolationType(IntType)                       84   InterpolationType(IntType)
 85 {                                                  85 {
 86   prepareTable(aProbFunc);                         86   prepareTable(aProbFunc);
 87 }                                                  87 }
 88                                                    88 
 89 RandGeneral::RandGeneral(HepRandomEngine* anEn     89 RandGeneral::RandGeneral(HepRandomEngine* anEngine,
 90                          const double* aProbFu     90                          const double* aProbFunc, 
 91        int theProbSize,                            91        int theProbSize, 
 92        int IntType )                               92        int IntType )
 93 : HepRandom(),                                     93 : HepRandom(),
 94   localEngine(anEngine),                           94   localEngine(anEngine), 
 95   nBins(theProbSize),                              95   nBins(theProbSize),
 96   InterpolationType(IntType)                       96   InterpolationType(IntType)
 97 {                                                  97 {
 98   prepareTable(aProbFunc);                         98   prepareTable(aProbFunc);
 99 }                                                  99 }
100                                                   100 
101 void RandGeneral::prepareTable(const double* a    101 void RandGeneral::prepareTable(const double* aProbFunc) {
102 //                                                102 //
103 // Private method called only by constructors.    103 // Private method called only by constructors.  Prepares theIntegralPdf.
104 //                                                104 //
105   if (nBins < 1) {                                105   if (nBins < 1) {
106     std::cerr <<                                  106     std::cerr << 
107   "RandGeneral constructed with no bins - will    107   "RandGeneral constructed with no bins - will use flat distribution\n";
108     useFlatDistribution();                        108     useFlatDistribution();
109     return;                                       109     return;
110   }                                               110   }
111                                                   111 
112   theIntegralPdf.resize(nBins+1);                 112   theIntegralPdf.resize(nBins+1);
113   theIntegralPdf[0] = 0;                          113   theIntegralPdf[0] = 0;
114   int ptn;                                        114   int ptn;
115   double weight;                                  115   double weight;
116                                                   116 
117   for ( ptn = 0; ptn<nBins; ++ptn ) {             117   for ( ptn = 0; ptn<nBins; ++ptn ) {
118     weight = aProbFunc[ptn];                      118     weight = aProbFunc[ptn];
119     if ( weight < 0 ) {                           119     if ( weight < 0 ) {
120     // We can't stomach negative bin contents,    120     // We can't stomach negative bin contents, they invalidate the 
121     // search algorithm when the distribution     121     // search algorithm when the distribution is fired.
122       std::cerr <<                                122       std::cerr << 
123   "RandGeneral constructed with negative-weigh    123   "RandGeneral constructed with negative-weight bin " << ptn <<
124   " = " << weight << " \n   -- will substitute    124   " = " << weight << " \n   -- will substitute 0 weight \n";
125       weight = 0;                                 125       weight = 0;
126     }                                             126     }
127     // std::cout << ptn << "  " << weight << "    127     // std::cout << ptn << "  " << weight << "  " << theIntegralPdf[ptn] << "\n";
128     theIntegralPdf[ptn+1] = theIntegralPdf[ptn    128     theIntegralPdf[ptn+1] = theIntegralPdf[ptn] + weight;
129   }                                               129   } 
130                                                   130 
131   if ( theIntegralPdf[nBins] <= 0 ) {             131   if ( theIntegralPdf[nBins] <= 0 ) {
132     std::cerr <<                                  132     std::cerr << 
133       "RandGeneral constructed nothing in bins    133       "RandGeneral constructed nothing in bins - will use flat distribution\n";
134     useFlatDistribution();                        134     useFlatDistribution();
135     return;                                       135     return;
136   }                                               136   }
137                                                   137 
138   for ( ptn = 0; ptn < nBins+1; ++ptn ) {         138   for ( ptn = 0; ptn < nBins+1; ++ptn ) {
139     theIntegralPdf[ptn] /= theIntegralPdf[nBin    139     theIntegralPdf[ptn] /= theIntegralPdf[nBins];
140     // std::cout << ptn << "  " << theIntegral    140     // std::cout << ptn << "  " << theIntegralPdf[ptn] << "\n";
141   }                                               141   }
142                                                   142 
143   // And another useful variable is ...           143   // And another useful variable is ...
144   oneOverNbins = 1.0 / nBins;                     144   oneOverNbins = 1.0 / nBins;
145                                                   145 
146   // One last chore:                              146   // One last chore:
147                                                   147 
148   if ( (InterpolationType != 0) && (Interpolat    148   if ( (InterpolationType != 0) && (InterpolationType != 1) ) {
149     std::cerr <<                                  149     std::cerr << 
150       "RandGeneral does not recognize IntType     150       "RandGeneral does not recognize IntType " << InterpolationType 
151       << "\n Will use type 0 (continuous linea    151       << "\n Will use type 0 (continuous linear interpolation \n";
152     InterpolationType = 0;                        152     InterpolationType = 0;
153   }                                               153   }
154                                                   154 
155 } // prepareTable()                               155 } // prepareTable()
156                                                   156 
157 void RandGeneral::useFlatDistribution() {         157 void RandGeneral::useFlatDistribution() {
158 //                                                158 //
159 // Private method called only by prepareTables    159 // Private method called only by prepareTables in case of user error. 
160 //                                                160 //
161     nBins = 1;                                    161     nBins = 1;
162     theIntegralPdf.resize(2);                     162     theIntegralPdf.resize(2);
163     theIntegralPdf[0] = 0;                        163     theIntegralPdf[0] = 0;
164     theIntegralPdf[1] = 1;                        164     theIntegralPdf[1] = 1;
165     oneOverNbins = 1.0;                           165     oneOverNbins = 1.0;
166     return;                                       166     return;
167                                                   167 
168 } // UseFlatDistribution()                        168 } // UseFlatDistribution()
169                                                   169 
170 //////////////////                                170 //////////////////
171 //  Destructor                                    171 //  Destructor
172 //////////////////                                172 //////////////////
173                                                   173 
174 RandGeneral::~RandGeneral() {                     174 RandGeneral::~RandGeneral() {
175 }                                                 175 }
176                                                   176 
177                                                  177 
178 ///////////////////                               178 ///////////////////
179 //  mapRandom(rand)                               179 //  mapRandom(rand)
180 ///////////////////                               180 ///////////////////
181                                                   181 
182 double RandGeneral::mapRandom(double rand) con    182 double RandGeneral::mapRandom(double rand) const {
183 //                                                183 //
184 // Private method to take the random (however     184 // Private method to take the random (however it is created) and map it
185 // according to the distribution.                 185 // according to the distribution.
186 //                                                186 //
187                                                   187 
188   int nbelow = 0;   // largest k such that I[k    188   int nbelow = 0;   // largest k such that I[k] is known to be <= rand
189   int nabove = nBins;     // largest k such th    189   int nabove = nBins;     // largest k such that I[k] is known to be >  rand
190   int middle;                                     190   int middle;
191                                                   191   
192   while (nabove > nbelow+1) {                     192   while (nabove > nbelow+1) {
193     middle = (nabove + nbelow+1)>>1;              193     middle = (nabove + nbelow+1)>>1;
194     if (rand >= theIntegralPdf[middle]) {         194     if (rand >= theIntegralPdf[middle]) {
195       nbelow = middle;                            195       nbelow = middle;
196     } else {                                      196     } else {
197       nabove = middle;                            197       nabove = middle;
198     }                                             198     }
199   } // after this loop, nabove is always nbelo    199   } // after this loop, nabove is always nbelow+1 and they straddle rad:
200     assert ( nabove == nbelow+1 );                200     assert ( nabove == nbelow+1 );
201     assert ( theIntegralPdf[nbelow] <= rand );    201     assert ( theIntegralPdf[nbelow] <= rand );
202     assert ( theIntegralPdf[nabove] >= rand );    202     assert ( theIntegralPdf[nabove] >= rand );  
203     // If a defective engine produces rand=1,     203     // If a defective engine produces rand=1, that will 
204     // still give sensible results so we relax    204     // still give sensible results so we relax the > rand assertion
205                                                   205 
206   if ( InterpolationType == 1 ) {                 206   if ( InterpolationType == 1 ) {
207                                                   207 
208     return nbelow * oneOverNbins;                 208     return nbelow * oneOverNbins;
209                                                   209 
210   } else {                                        210   } else {
211                                                   211 
212     double binMeasure = theIntegralPdf[nabove]    212     double binMeasure = theIntegralPdf[nabove] - theIntegralPdf[nbelow];
213     // binMeasure is always aProbFunc[nbelow],    213     // binMeasure is always aProbFunc[nbelow], 
214     // but we don't have aProbFunc any more so    214     // but we don't have aProbFunc any more so we subtract.
215                                                   215 
216     if ( binMeasure == 0 ) {                      216     if ( binMeasure == 0 ) { 
217   // rand lies right in a bin of measure 0.  S    217   // rand lies right in a bin of measure 0.  Simply return the center
218   // of the range of that bin.  (Any value bet    218   // of the range of that bin.  (Any value between k/N and (k+1)/N is 
219   // equally good, in this rare case.)            219   // equally good, in this rare case.)
220         return (nbelow + .5) * oneOverNbins;      220         return (nbelow + .5) * oneOverNbins;
221     }                                             221     }
222                                                   222 
223     double binFraction = (rand - theIntegralPd    223     double binFraction = (rand - theIntegralPdf[nbelow]) / binMeasure;
224                                                   224 
225     return (nbelow + binFraction) * oneOverNbi    225     return (nbelow + binFraction) * oneOverNbins;
226   }                                               226   }
227                                                   227 
228 } // mapRandom(rand)                              228 } // mapRandom(rand)
229                                                   229  
230 void RandGeneral::shootArray( HepRandomEngine*    230 void RandGeneral::shootArray( HepRandomEngine* anEngine,
231                             const int size, do    231                             const int size, double* vect )
232 {                                                 232 {
233    int i;                                         233    int i;
234                                                   234 
235    for (i=0; i<size; ++i) {                       235    for (i=0; i<size; ++i) {
236      vect[i] = shoot(anEngine);                   236      vect[i] = shoot(anEngine);
237    }                                              237    }
238 }                                                 238 }
239                                                   239 
240 void RandGeneral::fireArray( const int size, d    240 void RandGeneral::fireArray( const int size, double* vect )
241 {                                                 241 {
242    int i;                                         242    int i;
243                                                   243 
244    for (i=0; i<size; ++i) {                       244    for (i=0; i<size; ++i) {
245       vect[i] = fire();                           245       vect[i] = fire();
246    }                                              246    }
247 }                                                 247 }
248                                                   248 
249 std::ostream & RandGeneral::put ( std::ostream    249 std::ostream & RandGeneral::put ( std::ostream & os ) const {
250   long pr=os.precision(20);                    << 250   int pr=os.precision(20);
251   std::vector<unsigned long> t(2);                251   std::vector<unsigned long> t(2);
252   os << " " << name() << "\n";                    252   os << " " << name() << "\n";
253   os << "Uvec" << "\n";                           253   os << "Uvec" << "\n";
254   os << nBins << " " << oneOverNbins << " " <<    254   os << nBins << " " << oneOverNbins << " " << InterpolationType << "\n";    
255   t = DoubConv::dto2longs(oneOverNbins);          255   t = DoubConv::dto2longs(oneOverNbins);
256   os << t[0] << " " << t[1] << "\n";              256   os << t[0] << " " << t[1] << "\n";
257   assert (static_cast<int>(theIntegralPdf.size    257   assert (static_cast<int>(theIntegralPdf.size())==nBins+1);
258   for (unsigned int i=0; i<theIntegralPdf.size    258   for (unsigned int i=0; i<theIntegralPdf.size(); ++i) {
259     t = DoubConv::dto2longs(theIntegralPdf[i])    259     t = DoubConv::dto2longs(theIntegralPdf[i]);
260     os << theIntegralPdf[i] << " " << t[0] <<     260     os << theIntegralPdf[i] << " " << t[0] << " " << t[1] << "\n";
261   }                                               261   }
262   os.precision(pr);                               262   os.precision(pr);
263   return os;                                      263   return os;
264 }                                                 264 }
265                                                   265 
266 std::istream & RandGeneral::get ( std::istream    266 std::istream & RandGeneral::get ( std::istream & is ) {
267   std::string inName;                             267   std::string inName;
268   is >> inName;                                   268   is >> inName;
269   if (inName != name()) {                         269   if (inName != name()) {
270     is.clear(std::ios::badbit | is.rdstate());    270     is.clear(std::ios::badbit | is.rdstate());
271     std::cerr << "Mismatch when expecting to r    271     std::cerr << "Mismatch when expecting to read state of a "
272             << name() << " distribution\n"        272             << name() << " distribution\n"
273         << "Name found was " << inName            273         << "Name found was " << inName
274         << "\nistream is left in the badbit st    274         << "\nistream is left in the badbit state\n";
275     return is;                                    275     return is;
276   }                                               276   }
277   if (possibleKeywordInput(is, "Uvec", nBins))    277   if (possibleKeywordInput(is, "Uvec", nBins)) {
278     std::vector<unsigned long> t(2);              278     std::vector<unsigned long> t(2);
279     is >> nBins >> oneOverNbins >> Interpolati    279     is >> nBins >> oneOverNbins >> InterpolationType;
280     is >> t[0] >> t[1]; oneOverNbins = DoubCon    280     is >> t[0] >> t[1]; oneOverNbins = DoubConv::longs2double(t); 
281     theIntegralPdf.resize(nBins+1);               281     theIntegralPdf.resize(nBins+1);
282     for (unsigned int i=0; i<theIntegralPdf.si    282     for (unsigned int i=0; i<theIntegralPdf.size(); ++i) {
283       is >> theIntegralPdf[i] >> t[0] >> t[1];    283       is >> theIntegralPdf[i] >> t[0] >> t[1];
284       theIntegralPdf[i] = DoubConv::longs2doub    284       theIntegralPdf[i] = DoubConv::longs2double(t); 
285     }                                             285     }
286     return is;                                    286     return is;
287   }                                               287   }
288   // is >> nBins encompassed by possibleKeywor    288   // is >> nBins encompassed by possibleKeywordInput
289   is >> oneOverNbins >> InterpolationType;        289   is >> oneOverNbins >> InterpolationType;
290   theIntegralPdf.resize(nBins+1);                 290   theIntegralPdf.resize(nBins+1);
291   for (unsigned int i=0; i<theIntegralPdf.size    291   for (unsigned int i=0; i<theIntegralPdf.size(); ++i) is >> theIntegralPdf[i];
292   return is;                                      292   return is;
293 }                                                 293 }
294                                                   294 
295 }  // namespace CLHEP                             295 }  // namespace CLHEP
296                                                   296