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