TRandomNumberGenerator.hpp

Go to the documentation of this file.
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 //using Exponent::MathTools::CRandomNumberGenerator;
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                 // Check size
00129                 if (array && numberToGenerate >= 1)
00130                 {
00131                     // Handle based on type
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                 // Flag to indicate if state is stored already
00213                 static bool ready = false;
00214 
00215                 // Variables required to store gaus value
00216                 static double gaussianStore;
00217 
00218                 // Other variables
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                     // Compute two gaussian numbers
00236                     fractional = CMathTools::fastSquareRoot(1.0 * -CMathTools::fastLog(radius) / radius);
00237 
00238                     // Store one
00239                     gaussianStore = vertex1 * fractional;
00240 
00241                     // Store the other
00242                     gaussian = vertex2 * fractional;
00243 
00244                     // We dont need to generate next time
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

Infinity API - TRandomNumberGenerator.hpp Source File generated on 7 Mar 2007