Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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