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 #include <random>
00026 #include "cinder/Vector.h"
00027 
00028 namespace cinder {  
00029     
00030 class Rand {
00031  public:
00032     Rand()
00033         : mBase( 214u ), mHaveNextNextGaussian( false )
00034     {}
00035     
00036     Rand( unsigned long seed )
00037         : mBase( seed ), mHaveNextNextGaussian( false )
00038     {}
00039 
00041     void seed( unsigned long seedValue );
00042     
00044     bool nextBool()
00045     {
00046         return mBase() & 1;
00047     }
00048     
00050     int32_t nextInt()
00051     {
00052         return mBase();
00053     }
00054 
00056     uint32_t nextUint()
00057     {
00058         return mBase();
00059     }
00060     
00062     int32_t nextInt( int32_t v )
00063     {
00064         if( v <= 0 ) return 0;
00065         return mBase() % v;
00066     }
00067 
00069     uint32_t nextUint( uint32_t v )
00070     {
00071         if( v == 0 ) return 0;
00072         return mBase() % v;
00073     }
00074     
00076     int32_t nextInt( int32_t a, int32_t b )
00077     {
00078         return nextInt( b - a ) + a;
00079     }
00080     
00082     float nextFloat()
00083     {
00084         return mFloatGen(mBase);
00085     }
00086     
00088     float nextFloat( float v )
00089     {
00090         return mFloatGen(mBase) * v;
00091     }
00092     
00094     float nextFloat( float a, float b )
00095     {
00096         return mFloatGen(mBase) * ( b - a ) + a;
00097     }
00098     
00100     float posNegFloat( float a, float b )
00101     {
00102         if( nextBool() )
00103             return nextFloat( a, b );
00104         else
00105             return -nextFloat( a, b );
00106     }
00107     
00109     Vec3f nextVec3f()
00110     {
00111         float phi = nextFloat( (float)M_PI * 2.0f );
00112         float costheta = nextFloat( -1.0f, 1.0f );
00113         
00114         float rho = math<float>::sqrt( 1.0f - costheta * costheta ); 
00115         float x = rho * math<float>::cos( phi );
00116         float y = rho * math<float>::sin( phi );
00117         float z = costheta;
00118         
00119         return Vec3f( x, y, z );
00120     }
00121 
00123     Vec2f nextVec2f( )
00124     {
00125         float theta = nextFloat( (float)M_PI * 2.0f );
00126         return Vec2f( math<float>::cos( theta ), math<float>::sin( theta ) );
00127     }
00128     
00130     float nextGaussian()
00131     {
00132         if( mHaveNextNextGaussian ) {
00133             mHaveNextNextGaussian = false;
00134             return mNextNextGaussian;
00135         }
00136         else {
00137             float v1, v2, s;
00138             do {
00139                 v1 = 2.0f * nextFloat() - 1.0f;
00140                 v2 = 2.0f * nextFloat() - 1.0f;
00141 
00142                 s = v1 * v1 + v2 * v2;
00143             }
00144             while( s >= 1.0f || s == 0.0f );
00145 
00146             float m = math<float>::sqrt(-2.0f * math<float>::log(s)/s);
00147             
00148             mNextNextGaussian       = v2 * m;
00149             mHaveNextNextGaussian   = true;
00150 
00151             return v1 * m;
00152         }
00153     }    
00154     
00155     // STATICS
00157     static void randomize();
00158     
00160     static void randSeed( unsigned long seedValue );
00161     
00163     static bool randBool()
00164     {
00165         return sBase() & 1;
00166     }
00167     
00169     static int32_t randInt()
00170     {
00171         return sBase();
00172     }
00173 
00175     static uint32_t randUint()
00176     {
00177         return sBase();
00178     }
00179     
00181     static int32_t randInt( int32_t v )
00182     {
00183         if( v <= 0 ) return 0;
00184         else return sBase() % v;
00185     }
00186 
00188     static uint32_t randUint( uint32_t v )
00189     {
00190         if( v == 0 ) return 0;
00191         else return sBase() % v;
00192     }
00193     
00195     static int32_t randInt( int32_t a, int32_t b )
00196     {
00197         return randInt( b - a ) + a;
00198     }
00199     
00201     static float randFloat()
00202     {
00203         return sFloatGen(sBase);
00204     }
00205     
00207     static float randFloat( float v )
00208     {
00209         return sFloatGen(sBase) * v;
00210     }
00211     
00213     static float randFloat( float a, float b )
00214     {
00215         return sFloatGen(sBase) * ( b - a ) + a;
00216     }
00217     
00219     static float randPosNegFloat( float a, float b )
00220     {
00221         if( randBool() )
00222             return randFloat( a, b );
00223         else
00224             return -randFloat( a, b );
00225     }
00226     
00228     static Vec3f randVec3f()
00229     {
00230         float phi = randFloat( (float)M_PI * 2.0f );
00231         float costheta = randFloat( -1.0f, 1.0f );
00232         
00233         float rho = math<float>::sqrt( 1.0f - costheta * costheta ); 
00234         float x = rho * math<float>::cos( phi );
00235         float y = rho * math<float>::sin( phi );
00236         float z = costheta;
00237         
00238         return Vec3f( x, y, z );
00239     }
00240 
00242     static Vec2f randVec2f()
00243     {
00244         float theta = randFloat( (float)M_PI * 2.0f );
00245         return Vec2f( math<float>::cos( theta ), math<float>::sin( theta ) );
00246     }
00247     
00249     static float randGaussian() 
00250     {
00251         static bool  sHaveNextNextGaussian = false;
00252         static float sNextNextGaussian;
00253 
00254         if( sHaveNextNextGaussian ) {
00255             sHaveNextNextGaussian = false;
00256             return sNextNextGaussian;
00257         }
00258         else {
00259             float v1, v2, s;
00260             do {
00261                 v1 = 2.0f * sFloatGen(sBase) - 1.0f;
00262                 v2 = 2.0f * sFloatGen(sBase) - 1.0f;
00263 
00264                 s = v1 * v1 + v2 * v2;
00265             }
00266             while( s >= 1.0f || s == 0.0f );
00267 
00268             float m = math<float>::sqrt(-2.0f * math<float>::log(s)/s);
00269 
00270             sNextNextGaussian       = v2 * m;
00271             sHaveNextNextGaussian   = true;
00272             
00273             return v1 * m;
00274         }
00275     }
00276     
00277   private:
00278     std::mt19937 mBase;
00279     std::uniform_real_distribution<float>   mFloatGen;  
00280     float   mNextNextGaussian;    
00281     bool    mHaveNextNextGaussian;
00282     
00283     static std::mt19937 sBase;
00284     static std::uniform_real_distribution<float> sFloatGen;
00285 };
00286 
00288 inline void randSeed( unsigned long seedValue ) { Rand::randSeed( seedValue ); }
00289 
00291 inline bool randBool() { return Rand::randBool(); }
00292 
00294 inline int32_t randInt() { return Rand::randInt(); }
00295 
00297 inline int32_t randInt( int32_t v ) { return Rand::randInt( v ); }
00298 
00300 inline int32_t randInt( int32_t a, int32_t b ) { return Rand::randInt( a, b ); }
00301 
00303 inline float randFloat() { return Rand::randFloat(); }
00304 
00306 inline float randFloat( float v ) { return Rand::randFloat( v ); }
00307 
00309 inline float randFloat( float a, float b ) { return Rand::randFloat( a, b ); }
00310 
00312 inline float randPosNegFloat( float a, float b ) { return Rand::randPosNegFloat( a, b ); }
00313 
00315 inline Vec3f randVec3f() { return Rand::randVec3f(); }
00316 
00318 inline Vec2f randVec2f() { return Rand::randVec2f(); }
00319 
00321 inline float randGaussian() { return Rand::randGaussian(); }    
00322 
00323 } // namespace cinder