Geant4 11.3.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4UniformRandPool.cc
Go to the documentation of this file.
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
35#include "G4AutoDelete.hh"
36#include "G4Threading.hh"
37#include "globals.hh"
38
39#include <algorithm>
40#include <climits>
41#include <cstdlib>
42#include <cstring>
43
44// Not aligned memory
45//
46void create_pool(G4double*& buffer, G4int ps) { buffer = new G4double[ps]; }
47
48void destroy_pool(G4double*& buffer) { delete[] buffer; }
49
50#if defined(WIN32) || defined(__MINGW32__)
51// No bother with WIN
52void create_pool_align(G4double*& buffer, G4int ps) { create_pool(buffer, ps); }
53void destroy_pool_align(G4double*& buffer) { destroy_pool(buffer); }
54
55#else
56
57// Align memory pools
58// Assumption is: static_assert(sizeof(G4double)*CHAR_BIT==64)
59//
61{
62 // POSIX standard way
63 G4int errcode = posix_memalign((void**) &buffer, sizeof(G4double) * CHAR_BIT,
64 ps * sizeof(G4double));
65 if(errcode != 0)
66 {
67 G4Exception("G4UniformRandPool::create_pool_align()", "InvalidCondition",
68 FatalException, "Cannot allocate aligned buffer");
69 return;
70 }
71 return;
72}
73
74void destroy_pool_align(G4double*& buffer) { free(buffer); }
75#endif
76
78{
79 if(sizeof(G4double) * CHAR_BIT == 64)
80 {
81 create_pool_align(buffer, size);
82 }
83 else
84 {
85 create_pool(buffer, size);
86 }
87 Fill(size);
88}
89
91 : size(siz)
92{
93 if(sizeof(G4double) * CHAR_BIT == 64)
94 {
95 create_pool_align(buffer, size);
96 }
97 else
98 {
99 create_pool(buffer, size);
100 }
101 Fill(size);
102}
103
105{
106 if(sizeof(G4double) * CHAR_BIT == 64)
107 {
108 destroy_pool_align(buffer);
109 }
110 else
111 {
112 destroy_pool(buffer);
113 }
114}
115
116void G4UniformRandPool::Resize(/*PoolSize_t*/ G4int newSize)
117{
118 if(newSize != size)
119 {
120 destroy_pool(buffer);
121 create_pool(buffer, newSize);
122 size = newSize;
123 currentIdx = 0;
124 }
125 currentIdx = 0;
126}
127
128void G4UniformRandPool::Fill(G4int howmany)
129{
130 assert(howmany > 0 && howmany <= size);
131
132 // Fill buffer with random numbers
133 //
134 G4Random::getTheEngine()->flatArray(howmany, buffer);
135 currentIdx = 0;
136}
137
139{
140 assert(rnds != 0 && howmany > 0);
141
142 // if ( howmany <= 0 ) return;
143 // We generate at max "size" numbers at once, and
144 // We do not want to use recursive calls (expensive).
145 // We need to deal with the case howmany>size
146 // So:
147 // how many times I need to get "size" numbers?
148
149 const G4int maxcycles = howmany / size;
150
151 // This is the rest
152 //
153 const G4int peel = howmany % size;
154 assert(peel < size);
155
156 // Ok from now on I will get random numbers in group of "size"
157 // Note that if howmany<size maxcycles == 0
158 //
159 G4int cycle = 0;
160
161 // Consider the case howmany>size, then maxcycles>=1
162 // and we will request at least "size" rng, so
163 // let's start with a fresh buffer of numbers if needed
164 //
165 if(maxcycles > 0 && currentIdx > 0)
166 {
167 assert(currentIdx <= size);
168 Fill(currentIdx); //<size?currentIdx:size);
169 }
170 for(; cycle < maxcycles; ++cycle)
171 {
172 // We can use memcpy of std::copy, it turns out that the two are basically
173 // performance-wise equivalent (expected), since in my tests memcpy is a
174 // little bit faster, I use that
175 //
176 memcpy(rnds + (cycle * size), buffer, sizeof(G4double) * size);
177 // std::copy(buffer,buffer+size,rnds+(cycle*size));
178
179 // Get a new set of numbers
180 //
181 Fill(size); // Now currentIdx is 0 again
182 }
183
184 // If maxcycles>0 last think we did was to call Fill(size)
185 // so currentIdx == 0
186 // and it is guaranteed that peel<size, we have enough fresh random numbers
187 // but if maxcycles==0 currentIdx can be whatever, let's make sure we have
188 // enough fresh numbers
189 //
190 if(currentIdx + peel >= size)
191 {
192 Fill(currentIdx < size ? currentIdx : size);
193 }
194 memcpy(rnds + (cycle * size), buffer + currentIdx, sizeof(G4double) * peel);
195 // std::copy(buffer+currentIdx,buffer+(currentIdx+peel), rnds+(cycle*size));
196
197 // Advance index, we are done
198 //
199 currentIdx += peel;
200 assert(currentIdx <= size);
201}
202
203// Static interfaces implementing CLHEP methods
204
205namespace
206{
207 G4ThreadLocal G4UniformRandPool* rndpool = nullptr;
208}
209
211{
212 if(rndpool == nullptr)
213 {
214 rndpool = new G4UniformRandPool;
215 G4AutoDelete::Register(rndpool);
216 }
217 return rndpool->GetOne();
218}
219
221{
222 if(rndpool == nullptr)
223 {
224 rndpool = new G4UniformRandPool;
225 G4AutoDelete::Register(rndpool);
226 }
227 rndpool->GetMany(rnds, (unsigned int) howmany);
228}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
int G4int
Definition G4Types.hh:85
void create_pool(G4double *&buffer, G4int ps)
void destroy_pool_align(G4double *&buffer)
void create_pool_align(G4double *&buffer, G4int ps)
void destroy_pool(G4double *&buffer)
void GetMany(G4double *rnds, G4int howMany)
static void flatArray(G4int howmany, G4double *rnds)
void Resize(G4int newSize)
static G4double flat()
void Register(T *inst)
#define G4ThreadLocal
Definition tls.hh:77