Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

include/cinder/Rand.h

Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, The Barbarian Group
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 #pragma once
00024 
00025 #pragma push_macro("nil")
00026 #pragma push_macro("Nil")
00027 #undef nil
00028 #undef Nil
00029 #include <boost/random.hpp>
00030 #include <boost/random/uniform_int.hpp>
00031 #include <boost/random/uniform_real.hpp>
00032 #include <boost/random/mersenne_twister.hpp>
00033 #pragma pop_macro("Nil")
00034 #pragma pop_macro("nil")
00035 
00036 #include "cinder/Vector.h"
00037 
00038 namespace cinder {  
00039     
00040 class Rand {
00041  public:
00042     Rand()
00043         : mBase( 214u ), mFloatGen( mBase, boost::uniform_real<float>( 0.0f, 1.0f ) ), mIntGen( mBase, boost::uniform_int<>( 0, 2147483647 ) )
00044     {}
00045     
00046     Rand( uint32_t seed )
00047         : mBase( seed ), mFloatGen( mBase, boost::uniform_real<float>( 0.0f, 1.0f ) ), mIntGen( mBase, boost::uniform_int<>( 0, 2147483647 ) )
00048     {}
00049 
00051     void seed( uint32_t seedValue );
00052     
00054     bool nextBool()
00055     {
00056         return mIntGen() & 1;
00057     }
00058     
00060     int32_t nextInt()
00061     {
00062         return mIntGen();
00063     }
00064     
00066     int32_t nextInt( int32_t v )
00067     {
00068         return mIntGen() % v;
00069     }
00070     
00072     int32_t nextInt( int32_t a, int32_t b )
00073     {
00074         return nextInt( b - a ) + a;
00075     }
00076     
00078     float nextFloat()
00079     {
00080         return mFloatGen();
00081     }
00082     
00084     float nextFloat( float v )
00085     {
00086         return mFloatGen() * v;
00087     }
00088     
00090     float nextFloat( float a, float b )
00091     {
00092         return mFloatGen() * ( b - a ) + a;
00093     }
00094     
00096     float posNegFloat( float a, float b )
00097     {
00098         if( nextBool() )
00099             return nextFloat( a, b );
00100         else
00101             return -nextFloat( a, b );
00102     }
00103     
00105     Vec3f nextVec3f()
00106     {
00107         float phi = nextFloat( (float)M_PI * 2.0f );
00108         float costheta = nextFloat( -1.0f, 1.0f );
00109         
00110         float rho = math<float>::sqrt( 1.0f - costheta * costheta ); 
00111         float x = rho * math<float>::cos( phi );
00112         float y = rho * math<float>::sin( phi );
00113         float z = costheta;
00114         
00115         return Vec3f( x, y, z );
00116     }
00117 
00119     Vec2f nextVec2f( )
00120     {
00121         float theta = nextFloat( (float)M_PI * 2.0f );
00122         return Vec2f( math<float>::cos( theta ), math<float>::sin( theta ) );
00123     }
00124     
00126     float nextGaussian()
00127     {
00128         if (mHaveNextNextGaussian) {
00129             mHaveNextNextGaussian = false;
00130             return mNextNextGaussian;
00131         }
00132         else {
00133             float v1, v2, s;
00134             do {
00135                 v1 = 2.0f * nextFloat() - 1.0f;
00136                 v2 = 2.0f * nextFloat() - 1.0f;
00137                 
00138                 s = v1 * v1 + v2 * v2;
00139             }
00140             while (s >= 1.0f || s == 0.0f);
00141             
00142             float m = math<float>::sqrt(-2.0f * math<float>::log(s)/s);
00143             
00144             mNextNextGaussian       = v2 * m;
00145             mHaveNextNextGaussian   = true;
00146             
00147             return v1 * m;
00148         }
00149     }    
00150     
00151     // STATICS
00153     static void randomize();
00154     
00156     static void randSeed( uint32_t seedValue );
00157     
00159     static bool randBool()
00160     {
00161         return sIntGen() & 1;
00162     }
00163     
00165     static int32_t randInt()
00166     {
00167         return sIntGen();
00168     }
00169     
00171     static int32_t randInt( int32_t v )
00172     {
00173         if( v == 0 ) return 0;
00174         else return sIntGen() % v;
00175     }
00176     
00178     static int32_t randInt( int32_t a, int32_t b )
00179     {
00180         return randInt( b - a ) + a;
00181     }
00182     
00184     static float randFloat()
00185     {
00186         return sFloatGen();
00187     }
00188     
00190     static float randFloat( float v )
00191     {
00192         return sFloatGen() * v;
00193     }
00194     
00196     static float randFloat( float a, float b )
00197     {
00198         return sFloatGen() * ( b - a ) + a;
00199     }
00200     
00202     static float randPosNegFloat( float a, float b )
00203     {
00204         if( randBool() )
00205             return randFloat( a, b );
00206         else
00207             return -randFloat( a, b );
00208     }
00209     
00211     static Vec3f randVec3f()
00212     {
00213         float phi = randFloat( (float)M_PI * 2.0f );
00214         float costheta = randFloat( -1.0f, 1.0f );
00215         
00216         float rho = math<float>::sqrt( 1.0f - costheta * costheta ); 
00217         float x = rho * math<float>::cos( phi );
00218         float y = rho * math<float>::sin( phi );
00219         float z = costheta;
00220         
00221         return Vec3f( x, y, z );
00222     }
00223 
00225     static Vec2f randVec2f()
00226     {
00227         float theta = randFloat( (float)M_PI * 2.0f );
00228         return Vec2f( math<float>::cos( theta ), math<float>::sin( theta ) );
00229     }
00230     
00232     static float randGaussian() 
00233     {
00234         static bool  sHaveNextNextGaussian;
00235         static float sNextNextGaussian;
00236         
00237         if (sHaveNextNextGaussian) {
00238             sHaveNextNextGaussian = false;
00239             return sNextNextGaussian;
00240         }
00241         else {
00242             float v1, v2, s;
00243             do {
00244                 v1 = 2.0f * sFloatGen() - 1.0f;
00245                 v2 = 2.0f * sFloatGen() - 1.0f;
00246                 
00247                 s = v1 * v1 + v2 * v2;
00248             }
00249             while (s >= 1.0f || s == 0.0f);
00250             
00251             float m = math<float>::sqrt(-2.0f * math<float>::log(s)/s);
00252             
00253             sNextNextGaussian       = v2 * m;
00254             sHaveNextNextGaussian   = true;
00255             
00256             return v1 * m;
00257         }  
00258     }     
00259     
00260 private:
00261     boost::mt19937 mBase;
00262     boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > mFloatGen;   
00263     boost::variate_generator<boost::mt19937&, boost::uniform_int<> > mIntGen;
00264     float mNextNextGaussian;    
00265     bool mHaveNextNextGaussian;
00266     
00267     static boost::mt19937 sBase;
00268     static boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > sFloatGen;
00269     static boost::variate_generator<boost::mt19937&, boost::uniform_int<> > sIntGen;
00270 };
00271 
00273 inline void randSeed( uint32_t seedValue ) { Rand::randSeed( seedValue ); }
00274 
00276 inline bool randBool() { return Rand::randBool(); }
00277 
00279 inline int32_t randInt() { return Rand::randInt(); }
00280 
00282 inline int32_t randInt( int32_t v ) { return Rand::randInt( v ); }
00283 
00285 inline int32_t randInt( int32_t a, int32_t b ) { return Rand::randInt( a, b ); }
00286 
00288 inline float randFloat() { return Rand::randFloat(); }
00289 
00291 inline float randFloat( float v ) { return Rand::randFloat( v ); }
00292 
00294 inline float randFloat( float a, float b ) { return Rand::randFloat( a, b ); }
00295 
00297 inline float randPosNegFloat( float a, float b ) { return Rand::randPosNegFloat( a, b ); }
00298 
00300 inline Vec3f randVec3f() { return Rand::randVec3f(); }
00301 
00303 inline Vec2f randVec2f() { return Rand::randVec2f(); }
00304 
00306 inline float randGaussian() { return Rand::randGaussian(); }    
00307 
00308 } // namespace cinder