PBRT
|
00001 00002 // 00003 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas 00004 // Digital Ltd. LLC 00005 // 00006 // All rights reserved. 00007 // 00008 // Redistribution and use in source and binary forms, with or without 00009 // modification, are permitted provided that the following conditions are 00010 // met: 00011 // * Redistributions of source code must retain the above copyright 00012 // notice, this list of conditions and the following disclaimer. 00013 // * Redistributions in binary form must reproduce the above 00014 // copyright notice, this list of conditions and the following disclaimer 00015 // in the documentation and/or other materials provided with the 00016 // distribution. 00017 // * Neither the name of Industrial Light & Magic nor the names of 00018 // its contributors may be used to endorse or promote products derived 00019 // from this software without specific prior written permission. 00020 // 00021 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00024 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00025 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00026 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00027 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00028 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00029 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00030 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00031 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00032 // 00034 00035 00036 #ifndef INCLUDED_IMATHRANDOM_H 00037 #define INCLUDED_IMATHRANDOM_H 00038 00039 //----------------------------------------------------------------------------- 00040 // 00041 // Generators for uniformly distributed pseudo-random numbers and 00042 // functions that use those generators to generate numbers with 00043 // non-uniform distributions: 00044 // 00045 // class Rand32 00046 // class Rand48 00047 // solidSphereRand() 00048 // hollowSphereRand() 00049 // gaussRand() 00050 // gaussSphereRand() 00051 // 00052 // Note: class Rand48() calls erand48() and nrand48(), which are not 00053 // available on all operating systems. For compatibility we include 00054 // our own versions of erand48() and nrand48(). Our functions have 00055 // been reverse-engineered from the corresponding Unix/Linux man page. 00056 // 00057 //----------------------------------------------------------------------------- 00058 00059 #include <stdlib.h> 00060 #include <math.h> 00061 00062 namespace Imath { 00063 00064 //----------------------------------------------- 00065 // Fast random-number generator that generates 00066 // a uniformly distributed sequence with a period 00067 // length of 2^32. 00068 //----------------------------------------------- 00069 00070 class Rand32 00071 { 00072 public: 00073 00074 //------------ 00075 // Constructor 00076 //------------ 00077 00078 Rand32 (unsigned long int seed = 0); 00079 00080 00081 //-------------------------------- 00082 // Re-initialize with a given seed 00083 //-------------------------------- 00084 00085 void init (unsigned long int seed); 00086 00087 00088 //---------------------------------------------------------- 00089 // Get the next value in the sequence (range: [false, true]) 00090 //---------------------------------------------------------- 00091 00092 bool nextb (); 00093 00094 00095 //--------------------------------------------------------------- 00096 // Get the next value in the sequence (range: [0 ... 0xffffffff]) 00097 //--------------------------------------------------------------- 00098 00099 unsigned long int nexti (); 00100 00101 00102 //------------------------------------------------------ 00103 // Get the next value in the sequence (range: [0 ... 1[) 00104 //------------------------------------------------------ 00105 00106 float nextf (); 00107 00108 00109 //------------------------------------------------------------------- 00110 // Get the next value in the sequence (range [rangeMin ... rangeMax[) 00111 //------------------------------------------------------------------- 00112 00113 float nextf (float rangeMin, float rangeMax); 00114 00115 00116 private: 00117 00118 void next (); 00119 00120 unsigned long int _state; 00121 }; 00122 00123 00124 //-------------------------------------------------------- 00125 // Random-number generator based on the C Standard Library 00126 // functions erand48(), nrand48() & company; generates a 00127 // uniformly distributed sequence. 00128 //-------------------------------------------------------- 00129 00130 class Rand48 00131 { 00132 public: 00133 00134 //------------ 00135 // Constructor 00136 //------------ 00137 00138 Rand48 (unsigned long int seed = 0); 00139 00140 00141 //-------------------------------- 00142 // Re-initialize with a given seed 00143 //-------------------------------- 00144 00145 void init (unsigned long int seed); 00146 00147 00148 //---------------------------------------------------------- 00149 // Get the next value in the sequence (range: [false, true]) 00150 //---------------------------------------------------------- 00151 00152 bool nextb (); 00153 00154 00155 //--------------------------------------------------------------- 00156 // Get the next value in the sequence (range: [0 ... 0x7fffffff]) 00157 //--------------------------------------------------------------- 00158 00159 long int nexti (); 00160 00161 00162 //------------------------------------------------------ 00163 // Get the next value in the sequence (range: [0 ... 1[) 00164 //------------------------------------------------------ 00165 00166 double nextf (); 00167 00168 00169 //------------------------------------------------------------------- 00170 // Get the next value in the sequence (range [rangeMin ... rangeMax[) 00171 //------------------------------------------------------------------- 00172 00173 double nextf (double rangeMin, double rangeMax); 00174 00175 00176 private: 00177 00178 unsigned short int _state[3]; 00179 }; 00180 00181 00182 //------------------------------------------------------------ 00183 // Return random points uniformly distributed in a sphere with 00184 // radius 1 around the origin (distance from origin <= 1). 00185 //------------------------------------------------------------ 00186 00187 template <class Vec, class Rand> 00188 Vec 00189 solidSphereRand (Rand &rand); 00190 00191 00192 //------------------------------------------------------------- 00193 // Return random points uniformly distributed on the surface of 00194 // a sphere with radius 1 around the origin. 00195 //------------------------------------------------------------- 00196 00197 template <class Vec, class Rand> 00198 Vec 00199 hollowSphereRand (Rand &rand); 00200 00201 00202 //----------------------------------------------- 00203 // Return random numbers with a normal (Gaussian) 00204 // distribution with zero mean and unit variance. 00205 //----------------------------------------------- 00206 00207 template <class Rand> 00208 float 00209 gaussRand (Rand &rand); 00210 00211 00212 //---------------------------------------------------- 00213 // Return random points whose distance from the origin 00214 // has a normal (Gaussian) distribution with zero mean 00215 // and unit variance. 00216 //---------------------------------------------------- 00217 00218 template <class Vec, class Rand> 00219 Vec 00220 gaussSphereRand (Rand &rand); 00221 00222 00223 //--------------------------------- 00224 // erand48(), nrand48() and friends 00225 //--------------------------------- 00226 00227 double erand48 (unsigned short state[3]); 00228 double drand48 (); 00229 long int nrand48 (unsigned short state[3]); 00230 long int lrand48 (); 00231 void srand48 (long int seed); 00232 00233 00234 //--------------- 00235 // Implementation 00236 //--------------- 00237 00238 00239 inline void 00240 Rand32::init (unsigned long int seed) 00241 { 00242 _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL; 00243 } 00244 00245 00246 inline 00247 Rand32::Rand32 (unsigned long int seed) 00248 { 00249 init (seed); 00250 } 00251 00252 00253 inline void 00254 Rand32::next () 00255 { 00256 _state = 1664525L * _state + 1013904223L; 00257 } 00258 00259 00260 inline bool 00261 Rand32::nextb () 00262 { 00263 next (); 00264 // Return the 31st (most significant) bit, by and-ing with 2 ^ 31. 00265 return !!(_state & 2147483648UL); 00266 } 00267 00268 00269 inline unsigned long int 00270 Rand32::nexti () 00271 { 00272 next (); 00273 return _state & 0xffffffff; 00274 } 00275 00276 00277 inline float 00278 Rand32::nextf (float rangeMin, float rangeMax) 00279 { 00280 float f = nextf(); 00281 return rangeMin * (1 - f) + rangeMax * f; 00282 } 00283 00284 00285 inline void 00286 Rand48::init (unsigned long int seed) 00287 { 00288 seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL; 00289 00290 _state[0] = (unsigned short int) (seed & 0xFFFF); 00291 _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF); 00292 _state[2] = (unsigned short int) (seed & 0xFFFF); 00293 } 00294 00295 00296 inline 00297 Rand48::Rand48 (unsigned long int seed) 00298 { 00299 init (seed); 00300 } 00301 00302 00303 inline bool 00304 Rand48::nextb () 00305 { 00306 return Imath::nrand48 (_state) & 1; 00307 } 00308 00309 00310 inline long int 00311 Rand48::nexti () 00312 { 00313 return Imath::nrand48 (_state); 00314 } 00315 00316 00317 inline double 00318 Rand48::nextf () 00319 { 00320 return Imath::erand48 (_state); 00321 } 00322 00323 00324 inline double 00325 Rand48::nextf (double rangeMin, double rangeMax) 00326 { 00327 double f = nextf(); 00328 return rangeMin * (1 - f) + rangeMax * f; 00329 } 00330 00331 00332 template <class Vec, class Rand> 00333 Vec 00334 solidSphereRand (Rand &rand) 00335 { 00336 Vec v; 00337 00338 do 00339 { 00340 for (unsigned int i = 0; i < Vec::dimensions(); i++) 00341 v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); 00342 } 00343 while (v.length2() > 1); 00344 00345 return v; 00346 } 00347 00348 00349 template <class Vec, class Rand> 00350 Vec 00351 hollowSphereRand (Rand &rand) 00352 { 00353 Vec v; 00354 typename Vec::BaseType length; 00355 00356 do 00357 { 00358 for (unsigned int i = 0; i < Vec::dimensions(); i++) 00359 v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); 00360 00361 length = v.length(); 00362 } 00363 while (length > 1 || length == 0); 00364 00365 return v / length; 00366 } 00367 00368 00369 template <class Rand> 00370 float 00371 gaussRand (Rand &rand) 00372 { 00373 float x; // Note: to avoid numerical problems with very small 00374 float y; // numbers, we make these variables singe-precision 00375 float length2; // floats, but later we call the double-precision log() 00376 // and sqrt() functions instead of logf() and sqrtf(). 00377 do 00378 { 00379 x = float (rand.nextf (-1, 1)); 00380 y = float (rand.nextf (-1, 1)); 00381 length2 = x * x + y * y; 00382 } 00383 while (length2 >= 1 || length2 == 0); 00384 00385 return x * sqrt (-2 * log (double (length2)) / length2); 00386 } 00387 00388 00389 template <class Vec, class Rand> 00390 Vec 00391 gaussSphereRand (Rand &rand) 00392 { 00393 return hollowSphereRand <Vec> (rand) * gaussRand (rand); 00394 } 00395 00396 } // namespace Imath 00397 00398 #endif