Home | History | Annotate | Download | only in Imath
      1 ///////////////////////////////////////////////////////////////////////////
      2 //
      3 // Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
      4 // Digital Ltd. LLC
      5 //
      6 // All rights reserved.
      7 //
      8 // Redistribution and use in source and binary forms, with or without
      9 // modification, are permitted provided that the following conditions are
     10 // met:
     11 // *       Redistributions of source code must retain the above copyright
     12 // notice, this list of conditions and the following disclaimer.
     13 // *       Redistributions in binary form must reproduce the above
     14 // copyright notice, this list of conditions and the following disclaimer
     15 // in the documentation and/or other materials provided with the
     16 // distribution.
     17 // *       Neither the name of Industrial Light & Magic nor the names of
     18 // its contributors may be used to endorse or promote products derived
     19 // from this software without specific prior written permission.
     20 //
     21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32 //
     33 ///////////////////////////////////////////////////////////////////////////
     34 
     35 
     36 #ifndef INCLUDED_IMATHRANDOM_H
     37 #define INCLUDED_IMATHRANDOM_H
     38 
     39 //-----------------------------------------------------------------------------
     40 //
     41 //	Generators for uniformly distributed pseudo-random numbers and
     42 //	functions that use those generators to generate numbers with
     43 //	non-uniform distributions:
     44 //
     45 //		class Rand32
     46 //		class Rand48
     47 //		solidSphereRand()
     48 //		hollowSphereRand()
     49 //		gaussRand()
     50 //		gaussSphereRand()
     51 //
     52 //	Note: class Rand48() calls erand48() and nrand48(), which are not
     53 //	available on all operating systems.  For compatibility we include
     54 //	our own versions of erand48() and nrand48().  Our functions have
     55 //	been reverse-engineered from the corresponding Unix/Linux man page.
     56 //
     57 //-----------------------------------------------------------------------------
     58 
     59 #include <stdlib.h>
     60 #include <math.h>
     61 
     62 namespace Imath {
     63 
     64 //-----------------------------------------------
     65 // Fast random-number generator that generates
     66 // a uniformly distributed sequence with a period
     67 // length of 2^32.
     68 //-----------------------------------------------
     69 
     70 class Rand32
     71 {
     72   public:
     73 
     74     //------------
     75     // Constructor
     76     //------------
     77 
     78     Rand32 (unsigned long int seed = 0);
     79 
     80 
     81     //--------------------------------
     82     // Re-initialize with a given seed
     83     //--------------------------------
     84 
     85     void		init (unsigned long int seed);
     86 
     87 
     88     //----------------------------------------------------------
     89     // Get the next value in the sequence (range: [false, true])
     90     //----------------------------------------------------------
     91 
     92     bool		nextb ();
     93 
     94 
     95     //---------------------------------------------------------------
     96     // Get the next value in the sequence (range: [0 ... 0xffffffff])
     97     //---------------------------------------------------------------
     98 
     99     unsigned long int	nexti ();
    100 
    101 
    102     //------------------------------------------------------
    103     // Get the next value in the sequence (range: [0 ... 1[)
    104     //------------------------------------------------------
    105 
    106     float		nextf ();
    107 
    108 
    109     //-------------------------------------------------------------------
    110     // Get the next value in the sequence (range [rangeMin ... rangeMax[)
    111     //-------------------------------------------------------------------
    112 
    113     float		nextf (float rangeMin, float rangeMax);
    114 
    115 
    116   private:
    117 
    118     void		next ();
    119 
    120     unsigned long int	_state;
    121 };
    122 
    123 
    124 //--------------------------------------------------------
    125 // Random-number generator based on the C Standard Library
    126 // functions erand48(), nrand48() & company; generates a
    127 // uniformly distributed sequence.
    128 //--------------------------------------------------------
    129 
    130 class Rand48
    131 {
    132   public:
    133 
    134     //------------
    135     // Constructor
    136     //------------
    137 
    138     Rand48 (unsigned long int seed = 0);
    139 
    140 
    141     //--------------------------------
    142     // Re-initialize with a given seed
    143     //--------------------------------
    144 
    145     void		init (unsigned long int seed);
    146 
    147 
    148     //----------------------------------------------------------
    149     // Get the next value in the sequence (range: [false, true])
    150     //----------------------------------------------------------
    151 
    152     bool		nextb ();
    153 
    154 
    155     //---------------------------------------------------------------
    156     // Get the next value in the sequence (range: [0 ... 0x7fffffff])
    157     //---------------------------------------------------------------
    158 
    159     long int		nexti ();
    160 
    161 
    162     //------------------------------------------------------
    163     // Get the next value in the sequence (range: [0 ... 1[)
    164     //------------------------------------------------------
    165 
    166     double		nextf ();
    167 
    168 
    169     //-------------------------------------------------------------------
    170     // Get the next value in the sequence (range [rangeMin ... rangeMax[)
    171     //-------------------------------------------------------------------
    172 
    173     double		nextf (double rangeMin, double rangeMax);
    174 
    175 
    176   private:
    177 
    178     unsigned short int	_state[3];
    179 };
    180 
    181 
    182 //------------------------------------------------------------
    183 // Return random points uniformly distributed in a sphere with
    184 // radius 1 around the origin (distance from origin <= 1).
    185 //------------------------------------------------------------
    186 
    187 template <class Vec, class Rand>
    188 Vec
    189 solidSphereRand (Rand &rand);
    190 
    191 
    192 //-------------------------------------------------------------
    193 // Return random points uniformly distributed on the surface of
    194 // a sphere with radius 1 around the origin.
    195 //-------------------------------------------------------------
    196 
    197 template <class Vec, class Rand>
    198 Vec
    199 hollowSphereRand (Rand &rand);
    200 
    201 
    202 //-----------------------------------------------
    203 // Return random numbers with a normal (Gaussian)
    204 // distribution with zero mean and unit variance.
    205 //-----------------------------------------------
    206 
    207 template <class Rand>
    208 float
    209 gaussRand (Rand &rand);
    210 
    211 
    212 //----------------------------------------------------
    213 // Return random points whose distance from the origin
    214 // has a normal (Gaussian) distribution with zero mean
    215 // and unit variance.
    216 //----------------------------------------------------
    217 
    218 template <class Vec, class Rand>
    219 Vec
    220 gaussSphereRand (Rand &rand);
    221 
    222 
    223 //---------------------------------
    224 // erand48(), nrand48() and friends
    225 //---------------------------------
    226 
    227 double		erand48 (unsigned short state[3]);
    228 double		drand48 ();
    229 long int	nrand48 (unsigned short state[3]);
    230 long int	lrand48 ();
    231 void		srand48 (long int seed);
    232 
    233 
    234 //---------------
    235 // Implementation
    236 //---------------
    237 
    238 
    239 inline void
    240 Rand32::init (unsigned long int seed)
    241 {
    242     _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
    243 }
    244 
    245 
    246 inline
    247 Rand32::Rand32 (unsigned long int seed)
    248 {
    249     init (seed);
    250 }
    251 
    252 
    253 inline void
    254 Rand32::next ()
    255 {
    256     _state = 1664525L * _state + 1013904223L;
    257 }
    258 
    259 
    260 inline bool
    261 Rand32::nextb ()
    262 {
    263     next ();
    264     // Return the 31st (most significant) bit, by and-ing with 2 ^ 31.
    265     return !!(_state & 2147483648UL);
    266 }
    267 
    268 
    269 inline unsigned long int
    270 Rand32::nexti ()
    271 {
    272     next ();
    273     return _state & 0xffffffff;
    274 }
    275 
    276 
    277 inline float
    278 Rand32::nextf (float rangeMin, float rangeMax)
    279 {
    280     float f = nextf();
    281     return rangeMin * (1 - f) + rangeMax * f;
    282 }
    283 
    284 
    285 inline void
    286 Rand48::init (unsigned long int seed)
    287 {
    288     seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL;
    289 
    290     _state[0] = (unsigned short int) (seed & 0xFFFF);
    291     _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF);
    292     _state[2] = (unsigned short int) (seed & 0xFFFF);
    293 }
    294 
    295 
    296 inline
    297 Rand48::Rand48 (unsigned long int seed)
    298 {
    299     init (seed);
    300 }
    301 
    302 
    303 inline bool
    304 Rand48::nextb ()
    305 {
    306     return Imath::nrand48 (_state) & 1;
    307 }
    308 
    309 
    310 inline long int
    311 Rand48::nexti ()
    312 {
    313     return Imath::nrand48 (_state);
    314 }
    315 
    316 
    317 inline double
    318 Rand48::nextf ()
    319 {
    320     return Imath::erand48 (_state);
    321 }
    322 
    323 
    324 inline double
    325 Rand48::nextf (double rangeMin, double rangeMax)
    326 {
    327     double f = nextf();
    328     return rangeMin * (1 - f) + rangeMax * f;
    329 }
    330 
    331 
    332 template <class Vec, class Rand>
    333 Vec
    334 solidSphereRand (Rand &rand)
    335 {
    336     Vec v;
    337 
    338     do
    339     {
    340     for (unsigned int i = 0; i < Vec::dimensions(); i++)
    341         v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
    342     }
    343     while (v.length2() > 1);
    344 
    345     return v;
    346 }
    347 
    348 
    349 template <class Vec, class Rand>
    350 Vec
    351 hollowSphereRand (Rand &rand)
    352 {
    353     Vec v;
    354     typename Vec::BaseType length;
    355 
    356     do
    357     {
    358     for (unsigned int i = 0; i < Vec::dimensions(); i++)
    359         v[i] = (typename Vec::BaseType) rand.nextf (-1, 1);
    360 
    361     length = v.length();
    362     }
    363     while (length > 1 || length == 0);
    364 
    365     return v / length;
    366 }
    367 
    368 
    369 template <class Rand>
    370 float
    371 gaussRand (Rand &rand)
    372 {
    373     float x;		// Note: to avoid numerical problems with very small
    374     float y;		// numbers, we make these variables singe-precision
    375     float length2;	// floats, but later we call the double-precision log()
    376             // and sqrt() functions instead of logf() and sqrtf().
    377     do
    378     {
    379     x = float (rand.nextf (-1, 1));
    380     y = float (rand.nextf (-1, 1));
    381     length2 = x * x + y * y;
    382     }
    383     while (length2 >= 1 || length2 == 0);
    384 
    385     return x * sqrt (-2 * log (double (length2)) / length2);
    386 }
    387 
    388 
    389 template <class Vec, class Rand>
    390 Vec
    391 gaussSphereRand (Rand &rand)
    392 {
    393     return hollowSphereRand <Vec> (rand) * gaussRand (rand);
    394 }
    395 
    396 } // namespace Imath
    397 
    398 #endif
    399