00001 #ifndef __TRandomNumberGenerator__
00002 #define __TRandomNumberGenerator__
00003
00004 #include "CMathTools.hpp"
00005 #include "../Collections/TCollection.hpp"
00006 #include <cstdlib>
00007 #include <ctime>
00008 using Exponent::Collections::TCollection;
00009
00010 using Exponent::MathTools::CMathTools;
00011
00012
00013
00014 namespace Exponent
00015 {
00016 namespace MathTools
00017 {
00046 template <class TypeName> class TRandomNumberGenerator : public CCountedObject
00047 {
00049 EXPONENT_CLASS_DECLARATION;
00052
00053
00054 public:
00055
00056
00057
00062 enum ERandomNumberGenerationType
00063 {
00064 e_standardLibrary = 0,
00065 e_uniform,
00066 e_gaussian1,
00067 e_gaussian2,
00068 e_gaussian3
00069 };
00070
00071
00072
00076 TRandomNumberGenerator()
00077 {
00078 EXPONENT_CLASS_CONSTRUCTION(TRandomNumberGenerator<TypeName>);
00079 }
00080
00084 virtual ~TRandomNumberGenerator()
00085 {
00086 EXPONENT_CLASS_DESTRUCTION(TRandomNumberGenerator<TypeName>);
00087 }
00088
00089
00090
00095 void seed()
00096 {
00097 srand((unsigned int)time(NULL));
00098 }
00099
00100
00101
00107 TypeName getNewRandomNumber(const ERandomNumberGenerationType type)
00108 {
00109 switch(type)
00110 {
00111 case e_standardLibrary: return this->standardLibrary(); break;
00112 case e_uniform: return this->uniform(); break;
00113 case e_gaussian1: return this->gaussian1(); break;
00114 case e_gaussian2: return this->gaussian2(); break;
00115 case e_gaussian3: return this->gaussian3(); break;
00116 }
00117 return 0;
00118 }
00119
00126 void getNewRandomArray(TypeName *array, const long numberToGenerate, const ERandomNumberGenerationType type)
00127 {
00128
00129 if (array && numberToGenerate >= 1)
00130 {
00131
00132 switch(type)
00133 {
00134 case e_standardLibrary:
00135 for (long i = 0; i < numberToGenerate; i++)
00136 {
00137 array[i] = this->standardLibrary();
00138 }
00139 break;
00140 case e_uniform:
00141 for (long i = 0; i <numberToGenerate; i++)
00142 {
00143 array[i] = this->uniform();
00144 }
00145 break;
00146 case e_gaussian1:
00147 for (long i = 0; i < numberToGenerate; i++)
00148 {
00149 array[i] = this->gaussian1();
00150 }
00151 break;
00152 case e_gaussian2:
00153 for (long i = 0; i < numberToGenerate; i++)
00154 {
00155 array[i] = this->gaussian2();
00156 }
00157 break;
00158 case e_gaussian3:
00159 for (long i = 0; i < numberToGenerate; i++)
00160 {
00161 array[i] = this->gaussian3();
00162 }
00163 break;
00164 }
00165 }
00166 }
00167
00173 void getNewRandomArray(TCollection<TypeName> &array, const ERandomNumberGenerationType type)
00174 {
00175 this->getNewRandomArray(array.getMutableInternalBuffer(), array.getArraySize(), type);
00176 }
00177
00178
00179
00180 protected:
00181
00182
00183
00184 const static TypeName TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[3];
00186
00187
00192 TypeName uniform()
00193 {
00194 return (TypeName)(((TypeName)(rand() & RAND_MAX) / RAND_MAX - 0.5) * 2.0);
00195 }
00196
00201 TypeName standardLibrary()
00202 {
00203 return ((TypeName)rand()) / (TypeName)RAND_MAX;
00204 }
00205
00210 TypeName gaussian1()
00211 {
00212
00213 static bool ready = false;
00214
00215
00216 static double gaussianStore;
00217
00218
00219 TypeName vertex1;
00220 TypeName vertex2;
00221 TypeName radius;
00222 TypeName fractional;
00223 TypeName gaussian;
00224
00225 if (!ready)
00226 {
00227 do
00228 {
00229 vertex1 = uniform();
00230 vertex2 = uniform();
00231 radius = CMathTools::square(vertex1) + CMathTools::square(vertex2);
00232 }
00233 while(radius > (TypeName)1.0);
00234
00235
00236 fractional = CMathTools::fastSquareRoot(1.0 * -CMathTools::fastLog(radius) / radius);
00237
00238
00239 gaussianStore = vertex1 * fractional;
00240
00241
00242 gaussian = vertex2 * fractional;
00243
00244
00245 ready = true;
00246 }
00247 else
00248 {
00249 ready = false;
00250 gaussian = gaussianStore;
00251 }
00252
00253 return gaussian;
00254 }
00255
00260 TypeName gaussian2()
00261 {
00262 const TypeName random = ((TypeName)rand() / (TypeName)(RAND_MAX + 1));
00263 const TypeName randomMultiplied = random * TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[1];
00264 return (TypeName)((2.0 * (randomMultiplied + randomMultiplied + randomMultiplied) - 3.0 * (TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[1] - 1.0)) * TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[2]);
00265 }
00266
00271 TypeName gaussian3()
00272 {
00273 return CMathTools::fastSquareRoot(-2.0 * CMathTools::fastLog(this->standardLibrary())) * cos(CMathTools::CMATH_2PI_DOUBLE * this->standardLibrary());
00274 }
00275 };
00276
00278 EXPONENT_TEMPLATE_CLASS_IMPLEMENTATION(TRandomNumberGenerator<TypeName>, TypeName, CCountedObject);
00279 template<class TypeName>const TypeName TRandomNumberGenerator<TypeName>::TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[] =
00280 {
00281 (1 << 15) - 1,
00282 ((int)(TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[0] / 3)) + 1,
00283 1.0 / TRANDOM_NUMBER_GENERATOR_GAUSSIAN_COEFFICIENTS[1]
00284 };
00286 }
00287 }
00288 #endif // End of TRandomNumberGenerator.hpp