- Main Page
- Namespaces
- Classes
- Files
- Directories
- Related Pages

- File List
- File Members

# 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