![]() |
CASToR
1.0
Tomographic Reconstruction (PET/SPECT)
|
00001 00002 /* 00003 Implementation of class sRNG 00004 00005 - separators: X 00006 - doxygen: X 00007 - default initialization: X 00008 - CASTOR_DEBUG: none 00009 - CASTOR_VERBOSE: X 00010 */ 00011 00020 #include "sRNG.hh" 00021 00022 sRNG *sRNG::mp_Instance = NULL; 00023 00024 00025 // ===================================================================== 00026 // --------------------------------------------------------------------- 00027 // --------------------------------------------------------------------- 00028 // ===================================================================== 00032 sRNG::sRNG() 00033 { 00034 mp_Instance = NULL; 00035 m_verbose = 5; 00036 mp_Engines.clear(); 00037 mp_NonThreadedEngine = NULL; 00038 } 00039 00040 00041 00042 // ===================================================================== 00043 // --------------------------------------------------------------------- 00044 // --------------------------------------------------------------------- 00045 // ===================================================================== 00046 /* 00047 \brief Destructor of sRNG. Do nothing by default 00048 */ 00049 sRNG::~sRNG() 00050 { 00051 if(mp_NonThreadedEngine) delete mp_NonThreadedEngine; 00052 } 00053 00054 00055 00056 // ===================================================================== 00057 // --------------------------------------------------------------------- 00058 // --------------------------------------------------------------------- 00059 // ===================================================================== 00060 /* 00061 \fn Initialize 00062 \param a_nbThreads 00063 \brief Instanciate a number of RNG according to the number of threads used in openMP 00064 \details It uses a std::random_device as initial seed for each thread 00065 \return 0 if success, positive value otherwise 00066 */ 00067 int sRNG::Initialize(int a_nbThreads) 00068 { 00069 if(m_verbose >=3) if(m_verbose>=3) Cout("sRNG::Initialize ..."<< endl); 00070 00071 for(int th=0; th<a_nbThreads; th++) 00072 { 00073 std::random_device rd; 00074 mp_Engines.push_back(Engine(rd())); 00075 } 00076 00077 std::random_device rd_single; 00078 mp_NonThreadedEngine = new Engine(rd_single()); 00079 00080 return 0; 00081 } 00082 00083 00084 00085 // ===================================================================== 00086 // --------------------------------------------------------------------- 00087 // --------------------------------------------------------------------- 00088 // ===================================================================== 00098 int sRNG::Initialize(int64_t a_seed, int a_nbThreads) 00099 { 00100 if(m_verbose >=3) Cout("sRNG::Initialize with provided seed..."<< endl); 00101 00102 if (a_seed<0) 00103 { 00104 Cout("***** sRNG::Initialize()-> Error : seed for RNG should be >=0 !" << endl); 00105 return 1; 00106 } 00107 00108 for(int th=0; th<a_nbThreads; th++) 00109 { 00110 mp_Engines.push_back(Engine(a_seed)); 00111 if(m_verbose>=3) Cout("sRNG::Initialize()->Seed for thread "<< th << " : " << a_seed << endl); 00112 a_seed++; 00113 } 00114 00115 mp_NonThreadedEngine = new Engine(a_seed); 00116 00117 return 0; 00118 } 00119 00120 00121 00122 // ===================================================================== 00123 // --------------------------------------------------------------------- 00124 // --------------------------------------------------------------------- 00125 // ===================================================================== 00126 /* 00127 \fn GenerateRdmNber 00128 \brief Generate a random number for the thread whose index is recovered from the ompenMP function 00129 \todo Perhaps getting the thread index from argument rather than directly from the function. 00130 \todo But this implementation allows the RNG to be used anywhere in the code 00131 \todo Perhaps create a random distribution on the fly, and offer the possibility to select lower/upper bounds via argument parameters 00132 \return a random generated number in [0. ; 1.) 00133 */ 00134 double sRNG::GenerateRdmNber() 00135 { 00136 #ifdef CASTOR_VERBOSE 00137 if(m_verbose >=4) Cout("sRNG::GenerateRdmNber..."<< endl); 00138 #endif 00139 00140 int id=0; 00141 #ifdef CASTOR_OMP 00142 id = omp_get_thread_num(); 00143 #endif 00144 return mp_Distribution(mp_Engines[id]); 00145 } 00146 00147 00148 00149 // ===================================================================== 00150 // --------------------------------------------------------------------- 00151 // --------------------------------------------------------------------- 00152 // ===================================================================== 00153 /* 00154 \fn GenerateNonThreadedRdmNber 00155 \brief Generate a random number using the not thread safe random generator, for use in sequential 00156 parts of an otherwise multithreaded code 00157 \return double random number 00158 */ 00159 double sRNG::GenerateNonThreadedRdmNber() 00160 { 00161 #ifdef CASTOR_VERBOSE 00162 if(m_verbose >=4) Cout("sRNG::GenerateNonThreadedRdmNber..."<< endl); 00163 #endif 00164 00165 return mp_Distribution((*mp_NonThreadedEngine)); 00166 } 00167 00168 00169 00170 // ===================================================================== 00171 // --------------------------------------------------------------------- 00172 // --------------------------------------------------------------------- 00173 // ===================================================================== 00174 /* 00175 \fn GetNonThreadedGenerator 00176 \brief Get the not thread safe random generator, for use in sequential 00177 parts of an otherwise multithreaded code 00178 \return double random number 00179 */ 00180 sRNG::Engine* sRNG::GetNonThreadedGenerator() 00181 { 00182 #ifdef CASTOR_VERBOSE 00183 if(m_verbose >=4) Cout("sRNG::GetNonThreadedGenerator..."<< endl); 00184 #endif 00185 00186 return mp_NonThreadedEngine; 00187 }