Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/RanluxppEngine.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/RanluxppEngine.cc (Version 11.3.0) and /externals/clhep/src/RanluxppEngine.cc (Version 11.0.p1)


  1 //                                                  1 //
  2 // -*- C++ -*-                                      2 // -*- C++ -*-
  3 //                                                  3 //
  4 // -------------------------------------------      4 // -----------------------------------------------------------------------
  5 //                             HEP Random           5 //                             HEP Random
  6 //                       --- RanluxppEngine --      6 //                       --- RanluxppEngine ---
  7 //                     class implementation fi      7 //                     class implementation file
  8 // -------------------------------------------      8 // -----------------------------------------------------------------------
  9 // Implementation of the RANLUX++ generator         9 // Implementation of the RANLUX++ generator
 10 //                                                 10 //
 11 // RANLUX++ is an LCG equivalent of RANLUX usi     11 // RANLUX++ is an LCG equivalent of RANLUX using 576 bit numbers.
 12 //                                                 12 //
 13 // The idea of the generator (such as the init     13 // The idea of the generator (such as the initialization method) and the algorithm
 14 // for the modulo operation are described in       14 // for the modulo operation are described in
 15 // A. Sibidanov, *A revision of the subtract-w     15 // A. Sibidanov, *A revision of the subtract-with-borrow random numbergenerators*,
 16 // *Computer Physics Communications*, 221(2017     16 // *Computer Physics Communications*, 221(2017), 299-303,
 17 // preprint https://arxiv.org/pdf/1705.03123.p     17 // preprint https://arxiv.org/pdf/1705.03123.pdf
 18 //                                                 18 //
 19 // The code is loosely based on the Assembly i     19 // The code is loosely based on the Assembly implementation by A. Sibidanov
 20 // available at https://github.com/sibidanov/r     20 // available at https://github.com/sibidanov/ranluxpp/.
 21 //                                                 21 //
 22 // Compared to the original generator, this im     22 // Compared to the original generator, this implementation contains a fix to ensure
 23 // that the modulo operation of the LCG always     23 // that the modulo operation of the LCG always returns the smallest value congruent
 24 // to the modulus (based on notes by M. Lüsch     24 // to the modulus (based on notes by M. Lüscher). Also, the generator converts the
 25 // LCG state back to RANLUX numbers (implement     25 // LCG state back to RANLUX numbers (implementation based on notes by M. Lüscher).
 26 // This avoids a bias in the generated numbers     26 // This avoids a bias in the generated numbers because the upper bits of the LCG
 27 // state, that is smaller than the modulus \f$     27 // state, that is smaller than the modulus \f$ m = 2^{576} - 2^{240} + 1 \f$ (not
 28 // a power of 2!), have a higher probability o     28 // a power of 2!), have a higher probability of being 0 than 1. And finally, this
 29 // implementation draws 48 random bits for eac     29 // implementation draws 48 random bits for each generated floating point number
 30 // (instead of 52 bits as in the original gene     30 // (instead of 52 bits as in the original generator) to maintain the theoretical
 31 // properties from understanding the original      31 // properties from understanding the original transition function of RANLUX as a
 32 // chaotic dynamical system.                       32 // chaotic dynamical system.
 33 //                                                 33 //
 34 // These modifications and the portable implem     34 // These modifications and the portable implementation in general are described in
 35 // J. Hahnfeld, L. Moneta, *A Portable Impleme     35 // J. Hahnfeld, L. Moneta, *A Portable Implementation of RANLUX++*, vCHEP2021
 36 // preprint https://arxiv.org/pdf/2106.02504.p     36 // preprint https://arxiv.org/pdf/2106.02504.pdf
 37                                                    37 
 38 #include "CLHEP/Random/RanluxppEngine.h"           38 #include "CLHEP/Random/RanluxppEngine.h"
 39                                                    39 
 40 #include "CLHEP/Random/engineIDulong.h"            40 #include "CLHEP/Random/engineIDulong.h"
 41 #include "CLHEP/Utility/atomic_int.h"              41 #include "CLHEP/Utility/atomic_int.h"
 42                                                    42 
 43 #include "CLHEP/Random/ranluxpp/mulmod.h"          43 #include "CLHEP/Random/ranluxpp/mulmod.h"
 44 #include "CLHEP/Random/ranluxpp/ranlux_lcg.h"      44 #include "CLHEP/Random/ranluxpp/ranlux_lcg.h"
 45                                                    45 
 46 #include <cassert>                                 46 #include <cassert>
 47 #include <fstream>                                 47 #include <fstream>
 48 #include <ios>                                     48 #include <ios>
 49 #include <cstdint>                             << 
 50                                                    49 
 51 namespace CLHEP {                                  50 namespace CLHEP {
 52                                                    51 
 53 namespace {                                        52 namespace {
 54 // Number of instances with automatic seed sel     53 // Number of instances with automatic seed selection.
 55 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);          54 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
 56                                                    55 
 57 const uint64_t kA_2048[] = {                       56 const uint64_t kA_2048[] = {
 58     0xed7faa90747aaad9, 0x4cec2c78af55c101, 0x     57     0xed7faa90747aaad9, 0x4cec2c78af55c101, 0xe64dcb31c48228ec,
 59     0x6d8a15a13bee7cb0, 0x20b2ca60cb78c509, 0x     58     0x6d8a15a13bee7cb0, 0x20b2ca60cb78c509, 0x256c3d3c662ea36c,
 60     0xff74e54107684ed2, 0x492edfcc0cc8e753, 0x     59     0xff74e54107684ed2, 0x492edfcc0cc8e753, 0xb48c187cf5b22097,
 61 };                                                 60 };
 62 } // namespace                                     61 } // namespace
 63                                                    62 
 64 RanluxppEngine::RanluxppEngine() : HepRandomEn     63 RanluxppEngine::RanluxppEngine() : HepRandomEngine() {
 65   int numEngines = ++numberOfEngines;              64   int numEngines = ++numberOfEngines;
 66   setSeed(numEngines);                             65   setSeed(numEngines);
 67 }                                                  66 }
 68                                                    67 
 69 RanluxppEngine::RanluxppEngine(long seed) : He     68 RanluxppEngine::RanluxppEngine(long seed) : HepRandomEngine() {
 70   theSeed = seed;                                  69   theSeed = seed;
 71   setSeed(seed);                                   70   setSeed(seed);
 72 }                                                  71 }
 73                                                    72 
 74 RanluxppEngine::RanluxppEngine(std::istream &i     73 RanluxppEngine::RanluxppEngine(std::istream &is) : HepRandomEngine() {
 75   get(is);                                         74   get(is);
 76 }                                                  75 }
 77                                                    76 
 78 RanluxppEngine::~RanluxppEngine() = default;       77 RanluxppEngine::~RanluxppEngine() = default;
 79                                                    78 
 80 static constexpr int kMaxPos = 9 * 64;             79 static constexpr int kMaxPos = 9 * 64;
 81 static constexpr int kBits = 48;                   80 static constexpr int kBits = 48;
 82                                                    81 
 83 void RanluxppEngine::advance() {                   82 void RanluxppEngine::advance() {
 84   uint64_t lcg[9];                                 83   uint64_t lcg[9];
 85   to_lcg(fState, fCarry, lcg);                     84   to_lcg(fState, fCarry, lcg);
 86   mulmod(kA_2048, lcg);                            85   mulmod(kA_2048, lcg);
 87   to_ranlux(lcg, fState, fCarry);                  86   to_ranlux(lcg, fState, fCarry);
 88   fPosition = 0;                                   87   fPosition = 0;
 89 }                                                  88 }
 90                                                    89 
 91 uint64_t RanluxppEngine::nextRandomBits() {        90 uint64_t RanluxppEngine::nextRandomBits() {
 92   if (fPosition + kBits > kMaxPos) {               91   if (fPosition + kBits > kMaxPos) {
 93     advance();                                     92     advance();
 94   }                                                93   }
 95                                                    94 
 96   int idx = fPosition / 64;                        95   int idx = fPosition / 64;
 97   int offset = fPosition % 64;                     96   int offset = fPosition % 64;
 98   int numBits = 64 - offset;                       97   int numBits = 64 - offset;
 99                                                    98 
100   uint64_t bits = fState[idx] >> offset;           99   uint64_t bits = fState[idx] >> offset;
101   if (numBits < kBits) {                          100   if (numBits < kBits) {
102     bits |= fState[idx + 1] << numBits;           101     bits |= fState[idx + 1] << numBits;
103   }                                               102   }
104   bits &= ((uint64_t(1) << kBits) - 1);           103   bits &= ((uint64_t(1) << kBits) - 1);
105                                                   104 
106   fPosition += kBits;                             105   fPosition += kBits;
107   assert(fPosition <= kMaxPos && "position out    106   assert(fPosition <= kMaxPos && "position out of range!");
108                                                   107 
109   return bits;                                    108   return bits;
110 }                                                 109 }
111                                                   110 
112 double RanluxppEngine::flat() {                   111 double RanluxppEngine::flat() {
113   // RandomEngine wants a "double random value    112   // RandomEngine wants a "double random values ranging between ]0,1[", so
114   // exclude all zero bits.                       113   // exclude all zero bits.
115   uint64_t random;                                114   uint64_t random;
116   do {                                            115   do {
117     random = nextRandomBits();                    116     random = nextRandomBits();
118   } while (random == 0);                          117   } while (random == 0);
119                                                   118 
120   static constexpr double div = 1.0 / (uint64_    119   static constexpr double div = 1.0 / (uint64_t(1) << kBits);
121   return random * div;                            120   return random * div;
122 }                                                 121 }
123                                                   122 
124 void RanluxppEngine::flatArray(const int size,    123 void RanluxppEngine::flatArray(const int size, double *vect) {
125   for (int i = 0; i < size; i++) {                124   for (int i = 0; i < size; i++) {
126     vect[i] = flat();                             125     vect[i] = flat();
127   }                                               126   }
128 }                                                 127 }
129                                                   128 
130 void RanluxppEngine::setSeed(long seed, int) {    129 void RanluxppEngine::setSeed(long seed, int) {
131   theSeed = seed;                                 130   theSeed = seed;
132                                                   131 
133   uint64_t lcg[9];                                132   uint64_t lcg[9];
134   lcg[0] = 1;                                     133   lcg[0] = 1;
135   for (int i = 1; i < 9; i++) {                   134   for (int i = 1; i < 9; i++) {
136     lcg[i] = 0;                                   135     lcg[i] = 0;
137   }                                               136   }
138                                                   137 
139   uint64_t a_seed[9];                             138   uint64_t a_seed[9];
140   // Skip 2 ** 96 states.                         139   // Skip 2 ** 96 states.
141   powermod(kA_2048, a_seed, uint64_t(1) << 48)    140   powermod(kA_2048, a_seed, uint64_t(1) << 48);
142   powermod(a_seed, a_seed, uint64_t(1) << 48);    141   powermod(a_seed, a_seed, uint64_t(1) << 48);
143   // Skip more states according to seed.          142   // Skip more states according to seed.
144   powermod(a_seed, a_seed, seed);                 143   powermod(a_seed, a_seed, seed);
145   mulmod(a_seed, lcg);                            144   mulmod(a_seed, lcg);
146                                                   145 
147   to_ranlux(lcg, fState, fCarry);                 146   to_ranlux(lcg, fState, fCarry);
148   fPosition = 0;                                  147   fPosition = 0;
149 }                                                 148 }
150                                                   149 
151 void RanluxppEngine::setSeeds(const long *seed    150 void RanluxppEngine::setSeeds(const long *seeds, int) {
152   theSeeds = seeds;                               151   theSeeds = seeds;
153   setSeed(*seeds, 0);                             152   setSeed(*seeds, 0);
154 }                                                 153 }
155                                                   154 
156 void RanluxppEngine::skip(uint64_t n) {           155 void RanluxppEngine::skip(uint64_t n) {
157   int left = (kMaxPos - fPosition) / kBits;       156   int left = (kMaxPos - fPosition) / kBits;
158   assert(left >= 0 && "position was out of ran    157   assert(left >= 0 && "position was out of range!");
159   if (n < (uint64_t)left) {                       158   if (n < (uint64_t)left) {
160     // Just skip the next few entries in the c    159     // Just skip the next few entries in the currently available bits.
161     fPosition += n * kBits;                       160     fPosition += n * kBits;
162     return;                                       161     return;
163   }                                               162   }
164                                                   163 
165   n -= left;                                      164   n -= left;
166   // Need to advance and possibly skip over bl    165   // Need to advance and possibly skip over blocks.
167   int nPerState = kMaxPos / kBits;                166   int nPerState = kMaxPos / kBits;
168   int skip = int(n / nPerState);               << 167   int skip = (n / nPerState);
169                                                   168 
170   uint64_t a_skip[9];                             169   uint64_t a_skip[9];
171   powermod(kA_2048, a_skip, skip + 1);            170   powermod(kA_2048, a_skip, skip + 1);
172                                                   171 
173   uint64_t lcg[9];                                172   uint64_t lcg[9];
174   to_lcg(fState, fCarry, lcg);                    173   to_lcg(fState, fCarry, lcg);
175   mulmod(a_skip, lcg);                            174   mulmod(a_skip, lcg);
176   to_ranlux(lcg, fState, fCarry);                 175   to_ranlux(lcg, fState, fCarry);
177                                                   176 
178   // Potentially skip numbers in the freshly g    177   // Potentially skip numbers in the freshly generated block.
179   int remaining = int(n - skip * nPerState);   << 178   int remaining = n - skip * nPerState;
180   assert(remaining >= 0 && "should not end up     179   assert(remaining >= 0 && "should not end up at a negative position!");
181   fPosition = remaining * kBits;                  180   fPosition = remaining * kBits;
182   assert(fPosition <= kMaxPos && "position out    181   assert(fPosition <= kMaxPos && "position out of range!");
183 }                                                 182 }
184                                                   183 
185 void RanluxppEngine::saveStatus(const char fil    184 void RanluxppEngine::saveStatus(const char filename[]) const {
186   std::ofstream os(filename);                     185   std::ofstream os(filename);
187   put(os);                                        186   put(os);
188   os.close();                                     187   os.close();
189 }                                                 188 }
190                                                   189 
191 void RanluxppEngine::restoreStatus(const char     190 void RanluxppEngine::restoreStatus(const char filename[]) {
192   std::ifstream is(filename);                     191   std::ifstream is(filename);
193   get(is);                                        192   get(is);
194   is.close();                                     193   is.close();
195 }                                                 194 }
196                                                   195 
197 void RanluxppEngine::showStatus() const {         196 void RanluxppEngine::showStatus() const {
198   std::cout                                       197   std::cout
199       << "--------------------- RanluxppEngine    198       << "--------------------- RanluxppEngine status --------------------"
200       << std::endl;                               199       << std::endl;
201   std::cout << " fState[] = {";                   200   std::cout << " fState[] = {";
202   std::cout << std::hex << std::setfill('0');     201   std::cout << std::hex << std::setfill('0');
203   for (int i = 0; i < 9; i++) {                   202   for (int i = 0; i < 9; i++) {
204     if (i % 3 == 0) {                             203     if (i % 3 == 0) {
205       std::cout << std::endl << "     ";          204       std::cout << std::endl << "     ";
206     } else {                                      205     } else {
207       std::cout << " ";                           206       std::cout << " ";
208     }                                             207     }
209     std::cout << "0x" << std::setw(16) << fSta    208     std::cout << "0x" << std::setw(16) << fState[i] << ",";
210   }                                               209   }
211   std::cout << std::endl << " }" << std::endl;    210   std::cout << std::endl << " }" << std::endl;
212   std::cout << std::dec;                          211   std::cout << std::dec;
213   std::cout << " fCarry = " << fCarry << ", fP    212   std::cout << " fCarry = " << fCarry << ", fPosition = " << fPosition
214             << std::endl;                         213             << std::endl;
215   std::cout                                       214   std::cout
216       << "------------------------------------    215       << "----------------------------------------------------------------"
217       << std::endl;                               216       << std::endl;
218 }                                                 217 }
219                                                   218 
220 std::string RanluxppEngine::name() const { ret    219 std::string RanluxppEngine::name() const { return engineName(); }
221                                                   220 
222 std::string RanluxppEngine::engineName() { ret    221 std::string RanluxppEngine::engineName() { return "RanluxppEngine"; }
223                                                   222 
224 std::string RanluxppEngine::beginTag() { retur    223 std::string RanluxppEngine::beginTag() { return "RanluxppEngine-begin"; }
225                                                   224 
226 std::ostream &RanluxppEngine::put(std::ostream    225 std::ostream &RanluxppEngine::put(std::ostream &os) const {
227   os << beginTag() << "\n";                       226   os << beginTag() << "\n";
228   const std::vector<unsigned long> state = put    227   const std::vector<unsigned long> state = put();
229   for (unsigned long v : state) {                 228   for (unsigned long v : state) {
230     os << v << "\n";                              229     os << v << "\n";
231   }                                               230   }
232   return os;                                      231   return os;
233 }                                                 232 }
234                                                   233 
235 std::istream &RanluxppEngine::get(std::istream    234 std::istream &RanluxppEngine::get(std::istream &is) {
236   std::string tag;                                235   std::string tag;
237   is >> tag;                                      236   is >> tag;
238   if (tag != beginTag()) {                        237   if (tag != beginTag()) {
239     is.clear(std::ios::badbit | is.rdstate());    238     is.clear(std::ios::badbit | is.rdstate());
240     std::cerr << "No RanluxppEngine found at c    239     std::cerr << "No RanluxppEngine found at current position\n";
241     return is;                                    240     return is;
242   }                                               241   }
243   return getState(is);                            242   return getState(is);
244 }                                                 243 }
245                                                   244 
246 std::istream &RanluxppEngine::getState(std::is    245 std::istream &RanluxppEngine::getState(std::istream &is) {
247   std::vector<unsigned long> state;               246   std::vector<unsigned long> state;
248   state.reserve(VECTOR_STATE_SIZE);               247   state.reserve(VECTOR_STATE_SIZE);
249   for (unsigned int i = 0; i < VECTOR_STATE_SI    248   for (unsigned int i = 0; i < VECTOR_STATE_SIZE; i++) {
250     unsigned long v;                              249     unsigned long v;
251     is >> v;                                      250     is >> v;
252     state.push_back(v);                           251     state.push_back(v);
253   }                                               252   }
254                                                   253 
255   getState(state);                                254   getState(state);
256   return is;                                      255   return is;
257 }                                                 256 }
258                                                   257 
259 std::vector<unsigned long> RanluxppEngine::put    258 std::vector<unsigned long> RanluxppEngine::put() const {
260   std::vector<unsigned long> v;                   259   std::vector<unsigned long> v;
261   v.reserve(VECTOR_STATE_SIZE);                   260   v.reserve(VECTOR_STATE_SIZE);
262   v.push_back(engineIDulong<RanluxppEngine>())    261   v.push_back(engineIDulong<RanluxppEngine>());
263                                                   262 
264   // unsigned long is only guaranteed to be 32    263   // unsigned long is only guaranteed to be 32 bit wide, so chop up the 64 bit
265   // values in fState.                            264   // values in fState.
266   for (int i = 0; i < 9; i++) {                   265   for (int i = 0; i < 9; i++) {
267     unsigned long lower = static_cast<uint32_t    266     unsigned long lower = static_cast<uint32_t>(fState[i]);
268     v.push_back(lower);                           267     v.push_back(lower);
269     unsigned long upper = static_cast<uint32_t    268     unsigned long upper = static_cast<uint32_t>(fState[i] >> 32);
270     v.push_back(upper);                           269     v.push_back(upper);
271   }                                               270   }
272                                                   271 
273   v.push_back(fCarry);                            272   v.push_back(fCarry);
274   v.push_back(fPosition);                         273   v.push_back(fPosition);
275   return v;                                       274   return v;
276 }                                                 275 }
277                                                   276 
278 bool RanluxppEngine::get(const std::vector<uns    277 bool RanluxppEngine::get(const std::vector<unsigned long> &v) {
279   if (v[0] != engineIDulong<RanluxppEngine>())    278   if (v[0] != engineIDulong<RanluxppEngine>()) {
280     std::cerr << "RanluxppEngine::get(): "        279     std::cerr << "RanluxppEngine::get(): "
281               << "vector has wrong ID word - s    280               << "vector has wrong ID word - state unchanged" << std::endl;
282     return false;                                 281     return false;
283   }                                               282   }
284   return getState(v);                             283   return getState(v);
285 }                                                 284 }
286                                                   285 
287 bool RanluxppEngine::getState(const std::vecto    286 bool RanluxppEngine::getState(const std::vector<unsigned long> &v) {
288   if (v.size() != VECTOR_STATE_SIZE) {            287   if (v.size() != VECTOR_STATE_SIZE) {
289     std::cerr << "RanluxppEngine::getState():     288     std::cerr << "RanluxppEngine::getState(): "
290               << "vector has wrong length - st    289               << "vector has wrong length - state unchanged" << std::endl;
291     return false;                                 290     return false;
292   }                                               291   }
293                                                   292 
294   // Assemble the state vector (see RanluxppEn    293   // Assemble the state vector (see RanluxppEngine::put).
295   for (int i = 0; i < 9; i++) {                   294   for (int i = 0; i < 9; i++) {
296     uint64_t lower = v[2 * i + 1];                295     uint64_t lower = v[2 * i + 1];
297     uint64_t upper = v[2 * i + 2];                296     uint64_t upper = v[2 * i + 2];
298     fState[i] = (upper << 32) + lower;            297     fState[i] = (upper << 32) + lower;
299   }                                               298   }
300   fCarry = (unsigned int)v[19];                << 299   fCarry = v[19];
301   fPosition = (int)v[20];                      << 300   fPosition = v[20];
302                                                   301 
303   return true;                                    302   return true;
304 }                                                 303 }
305                                                   304 
306 } // namespace CLHEP                              305 } // namespace CLHEP
307                                                   306