PBRT
/home/felix/UBC/projects/AdaptiveLightfieldSampling/pbrt_v2/src/3rdparty/ilmbase-1.0.2/ImathRandom.h
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