ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4UniformRandPool.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4UniformRandPool.cc
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 // G4UniformRandPool implementation
29 //
30 // Author: A.Dotti (SLAC)
31 // ------------------------------------------------------------
32 
33 #include "G4UniformRandPool.hh"
34 #include "globals.hh"
35 #include "G4Threading.hh"
36 #include "G4AutoDelete.hh"
37 
38 #include <climits>
39 #include <stdlib.h>
40 #include <algorithm>
41 #include <cstring>
42 
43 // Not aligned memory
44 //
46 {
47  buffer = new G4double[ps];
48 }
49 
51 {
52  delete[] buffer;
53 }
54 
55 #if defined(WIN32)
56 // No bother with WIN
58 {
59  create_pool(buffer,ps);
60 }
62 {
63  destroy_pool(buffer);
64 }
65 
66 #else
67 
68 // Align memory pools
69 // Assumption is: static_assert(sizeof(G4double)*CHAR_BIT==64)
70 //
72 {
73  // POSIX standard way
74  G4int errcode = posix_memalign( (void**) &buffer ,
75  sizeof(G4double)*CHAR_BIT,
76  ps*sizeof(G4double));
77  if ( errcode != 0 )
78  {
79  G4Exception("G4UniformRandPool::create_pool_align()",
80  "InvalidCondition", FatalException,
81  "Cannot allocate aligned buffer");
82  return;
83  }
84  return;
85 }
86 
88 {
89  free(buffer);
90 }
91 #endif
92 
94  : size(G4UNIFORMRANDPOOL_DEFAULT_POOLSIZE), buffer(0), currentIdx(0)
95 {
96  if ( sizeof(G4double)*CHAR_BIT==64 )
97  {
99  }
100  else
101  {
103  }
104  Fill(size);
105 }
106 
108  : size(siz), buffer(0), currentIdx(0)
109 {
110  if ( sizeof(G4double)*CHAR_BIT==64 )
111  {
113  }
114  else
115  {
117  }
118  Fill(size);
119 
120 }
121 
123 {
124  if ( sizeof(G4double)*CHAR_BIT==64 )
125  {
127  }
128  else
129  {
131  }
132 }
133 
134 void G4UniformRandPool::Resize(/*PoolSize_t*/ G4int newSize )
135 {
136  if ( newSize != size )
137  {
139  create_pool(buffer,newSize);
140  size=newSize;
141  currentIdx = 0;
142  }
143  currentIdx = 0;
144 }
145 
147 {
148  assert(howmany>0 && howmany <= size);
149 
150  // Fill buffer with random numbers
151  //
152  G4Random::getTheEngine()->flatArray(howmany,buffer);
153  currentIdx = 0;
154 }
155 
157 {
158  assert(rnds!=0 && howmany>0);
159 
160  // if ( howmany <= 0 ) return;
161  // We generate at max "size" numbers at once, and
162  // We do not want to use recursive calls (expensive).
163  // We need to deal with the case howmany>size
164  // So:
165  // how many times I need to get "size" numbers?
166 
167  const G4int maxcycles = howmany/size;
168 
169  // This is the rest
170  //
171  const G4int peel = howmany%size;
172  assert(peel<size);
173 
174  // Ok from now on I will get random numbers in group of "size"
175  // Note that if howmany<size maxcycles == 0
176  //
177  G4int cycle = 0;
178 
179  // Consider the case howmany>size, then maxcycles>=1
180  // and we will request at least "size" rng, so
181  // let's start with a fresh buffer of numbers if needed
182  //
183  if ( maxcycles>0 && currentIdx>0 )
184  {
185  assert(currentIdx<=size);
186  Fill(currentIdx);//<size?currentIdx:size);
187  }
188  for ( ; cycle < maxcycles ; ++cycle )
189  {
190  // We can use memcpy of std::copy, it turns out that the two are basically
191  // performance-wise equivalent (expected), since in my tests memcpy is a
192  // little bit faster, I use that
193  //
194  memcpy(rnds+(cycle*size),buffer,sizeof(G4double)*size );
195  // std::copy(buffer,buffer+size,rnds+(cycle*size));
196 
197  // Get a new set of numbers
198  //
199  Fill(size); // Now currentIdx is 0 again
200  }
201 
202  // If maxcycles>0 last think we did was to call Fill(size)
203  // so currentIdx == 0
204  // and it is guaranteed that peel<size, we have enough fresh random numbers
205  // but if maxcycles==0 currentIdx can be whatever, let's make sure we have
206  // enough fresh numbers
207  //
208  if (currentIdx + peel >= size)
209  {
211  }
212  memcpy(rnds+(cycle*size) , buffer+currentIdx , sizeof(G4double)*peel );
213  // std::copy(buffer+currentIdx,buffer+(currentIdx+peel), rnds+(cycle*size));
214 
215  // Advance index, we are done
216  //
217  currentIdx+=peel;
218  assert(currentIdx<=size);
219 }
220 
221 // Static interfaces implementing CLHEP methods
222 
223 namespace
224 {
225  G4ThreadLocal G4UniformRandPool* rndpool = 0;
226 }
227 
229 {
230  if ( rndpool == 0 )
231  {
232  rndpool = new G4UniformRandPool;
233  G4AutoDelete::Register(rndpool);
234  }
235  return rndpool->GetOne();
236 }
237 
239 {
240  if ( rndpool == 0 )
241  {
242  rndpool = new G4UniformRandPool;
243  G4AutoDelete::Register(rndpool);
244  }
245  rndpool->GetMany(rnds,(unsigned int)howmany);
246 }