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