opennurbs_rand.cpp
Go to the documentation of this file.
00001 /* $NoKeywords: $ */
00002 /*
00003 //
00004 // Copyright (c) 1993-2012 Robert McNeel & Associates. All rights reserved.
00005 // OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
00006 // McNeel & Associates.
00007 //
00008 // THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
00009 // ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
00010 // MERCHANTABILITY ARE HEREBY DISCLAIMED.
00011 //                              
00012 // For complete openNURBS copyright information see <http://www.opennurbs.org>.
00013 //
00015 */
00016 
00017 #include "pcl/surface/3rdparty/opennurbs/opennurbs.h"
00018 
00019 // This source code is from 
00020 // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
00021 // and its copyright and license are reproduced below.
00022 // It is included in opennurbs because we need a thread safe and
00023 // platform independent way to get a decent 32 bit random number.
00024 
00025 /* 
00026    A C-program for MT19937, with initialization improved 2002/1/26.
00027    Coded by Takuji Nishimura and Makoto Matsumoto.
00028 
00029    Before using, initialize the state by using init_genrand(seed)  
00030    or init_by_array(init_key, key_length).
00031 
00032    Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
00033    All rights reserved.                          
00034 
00035    Redistribution and use in source and binary forms, with or without
00036    modification, are permitted provided that the following conditions
00037    are met:
00038 
00039      1. Redistributions of source code must retain the above copyright
00040         notice, this list of conditions and the following disclaimer.
00041 
00042      2. Redistributions in binary form must reproduce the above copyright
00043         notice, this list of conditions and the following disclaimer in the
00044         documentation and/or other materials provided with the distribution.
00045 
00046      3. The names of its contributors may not be used to endorse or promote 
00047         products derived from this software without specific prior written 
00048         permission.
00049 
00050    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00051    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00052    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00053    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00054    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00055    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00056    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00057    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00058    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00059    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00060    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00061 
00062 
00063    Any feedback is very welcome.
00064    http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
00065    email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
00066 */
00067 
00068 /* Period parameters */  
00069 #define N 624 /* If you change the value of N, update the length of ON_RANDOM_NUMBER_CONTEXT m_t[] to match. */
00070 #define M 397
00071 #define MATRIX_A 0x9908b0dfUL   /* constant vector a */
00072 #define UPPER_MASK 0x80000000UL /* most significant w-r bits */
00073 #define LOWER_MASK 0x7fffffffUL /* least significant r bits */
00074 
00075 
00076 
00077 
00078 //static unsigned long mt[N]; /* the array for the state vector  */
00079 //static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
00080 
00081 /* initializes mt[N] with a seed */
00082 void on_random_number_seed(ON__UINT32 s,ON_RANDOM_NUMBER_CONTEXT* randcontext)
00083 {
00084   ON__UINT32 i, u;
00085 
00086 #if defined(ON_COMPILER_MSC)
00087 #pragma warning( push )
00088 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
00089 #endif
00090   if ( N*sizeof(randcontext->mt[0]) != sizeof(randcontext->mt) )
00091   {
00092     ON_ERROR("the mt[] array in struct ON_RANDOM_NUMBER_CONTEXT must have length N.");
00093   }
00094 #if defined(ON_COMPILER_MSC)
00095 #pragma warning( pop )
00096 #endif
00097 
00098   randcontext->mt[0] = u = s & 0xffffffffUL;
00099   for (i=1; i<N; i++) 
00100   {
00101     u = (1812433253UL * (u ^ (u >> 30)) + i); 
00102     /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
00103     /* In the previous versions, MSBs of the seed affect   */
00104     /* only MSBs of the array mt[].                        */
00105     /* 2002/01/09 modified by Makoto Matsumoto             */
00106 
00107     u &= 0xffffffffUL;
00108     /* for confused people who end up with sizeof(ON__UINT32) > 4*/
00109 
00110     randcontext->mt[i] = u;
00111   }
00112 
00113   randcontext->mti = N;
00114 }
00115 
00116 
00121 //void on_srand_by_array(unsigned long init_key[], int key_length)
00122 //{
00123 //    int i, j, k;
00124 //    init_genrand(19650218UL);
00125 //    i=1; j=0;
00126 //    k = (N>key_length ? N : key_length);
00127 //    for (; k; k--) {
00128 //        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL))
00129 //          + init_key[j] + j; /* non linear */
00130 //        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
00131 //        i++; j++;
00132 //        if (i>=N) { mt[0] = mt[N-1]; i=1; }
00133 //        if (j>=key_length) j=0;
00134 //    }
00135 //    for (k=N-1; k; k--) {
00136 //        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
00137 //          - i; /* non linear */
00138 //        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
00139 //        i++;
00140 //        if (i>=N) { mt[0] = mt[N-1]; i=1; }
00141 //    }
00142 //
00143 //    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
00144 //}
00145 
00146 /* generates a random number on [0,0xffffffff]-interval */
00147 ON__UINT32 on_random_number(struct ON_RANDOM_NUMBER_CONTEXT* randcontext)
00148 {
00149   static const ON__UINT32 mag01[2]={0x0UL, MATRIX_A};
00150   ON__UINT32 kk, y;
00151   /* mag01[x] = x * MATRIX_A  for x=0,1 */
00152 
00153   if (randcontext->mti >= N) 
00154   {
00155     /* generate N words at one time */
00156     if (randcontext->mti >= N+1)
00157     {
00158       /* if randcontext has never been initialized */
00159       on_random_number_seed(5489UL,randcontext); /* a default initial seed is used */
00160     }
00161 
00162     for (kk=0;kk<N-M;kk++)
00163     {
00164       y = (randcontext->mt[kk]&UPPER_MASK)|(randcontext->mt[kk+1]&LOWER_MASK);
00165       randcontext->mt[kk] = randcontext->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
00166     }
00167     for (;kk<N-1;kk++) 
00168     {
00169       y = (randcontext->mt[kk]&UPPER_MASK)|(randcontext->mt[kk+1]&LOWER_MASK);
00170       randcontext->mt[kk] = randcontext->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
00171     }
00172     y = (randcontext->mt[N-1]&UPPER_MASK)|(randcontext->mt[0]&LOWER_MASK);
00173     randcontext->mt[N-1] = randcontext->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
00174 
00175     randcontext->mti = 0;
00176   }
00177 
00178   y = randcontext->mt[randcontext->mti++];
00179 
00180   /* Tempering */
00181   y ^= (y >> 11);
00182   y ^= (y << 7) & 0x9d2c5680UL;
00183   y ^= (y << 15) & 0xefc60000UL;
00184   y ^= (y >> 18);
00185 
00186   return y;
00187 }
00188 
00189 
00190 
00191 
00192 
00193 // non-thread safe context used by on_srand() and on_rand().
00194 static struct ON_RANDOM_NUMBER_CONTEXT static_randcontext = {N+1,{0}};
00195 
00196 void on_srand(ON__UINT32 s)
00197 {
00198   // This function is not thread safe!  
00199   // It initializes a static global which is also used by on_rand().
00200   struct ON_RANDOM_NUMBER_CONTEXT randcontext;
00201   on_random_number_seed(s,&randcontext);
00202   memcpy(&static_randcontext,&randcontext,sizeof(static_randcontext));
00203 }
00204 
00205 /* generates a random number on [0,0xffffffff]-interval */
00206 ON__UINT32 on_rand(void)
00207 {
00208   // This function is not thread safe!  
00209   // It modifies a static global which is also used by on_srand().
00210   return on_random_number(&static_randcontext);
00211 }
00212 
00213 
00214 
00215 
00216 
00217 
00219 //long genrand_int31(void)
00220 //{
00221 //    return (long)(on_rand()>>1);
00222 //}
00223 //
00225 //double genrand_real1(void)
00226 //{
00227 //    return on_rand()*(1.0/4294967295.0); 
00228 //    /* divided by 2^32-1 */ 
00229 //}
00230 //
00232 //double genrand_real2(void)
00233 //{
00234 //    return on_rand()*(1.0/4294967296.0); 
00235 //    /* divided by 2^32 */
00236 //}
00237 //
00239 //double genrand_real3(void)
00240 //{
00241 //    return (((double)on_rand()) + 0.5)*(1.0/4294967296.0); 
00242 //    /* divided by 2^32 */
00243 //}
00244 //
00246 //double genrand_res53(void) 
00247 //{ 
00248 //    unsigned long a=genrand_int32()>>5, b=genrand_int32()>>6; 
00249 //    return(a*67108864.0+b)*(1.0/9007199254740992.0); 
00250 //} 
00252 
00253 
00254 ON_RandomNumberGenerator::ON_RandomNumberGenerator()
00255 {
00256   m_rand_context.mti = 0xFFFFFFFF;
00257 }
00258 
00259 void ON_RandomNumberGenerator::Seed( ON__UINT32 s )
00260 {
00261   on_random_number_seed(s,&m_rand_context);
00262 }
00263 
00264 ON__UINT32 ON_RandomNumberGenerator::RandomNumber()
00265 {
00266   return on_random_number(&m_rand_context);
00267 }
00268 
00269 double ON_RandomNumberGenerator::RandomDouble()
00270 {
00271   return ((double)on_random_number(&m_rand_context))/4294967295.0;
00272 }
00273 
00274 double ON_RandomNumberGenerator::RandomDouble(double t0, double t1)
00275 {
00276   const double s = ((double)on_random_number(&m_rand_context))/4294967295.0;
00277   return ((1.0-s)*t0 + s*t1);
00278 }
00279 
00280 static void Swap1(size_t count, unsigned char* a, unsigned char* b)
00281 {
00282   unsigned char t;
00283   while (count--)
00284   {
00285     t = *a;
00286     *a = *b;
00287     *b = t;
00288     a++;
00289     b++;
00290   }
00291 }
00292 
00293 static void Swap4(size_t count, ON__UINT32* a, ON__UINT32* b)
00294 {
00295   ON__UINT32 t;
00296   while (count--)
00297   {
00298     t = *a;
00299     *a = *b;
00300     *b = t;
00301     a++;
00302     b++;
00303   }
00304 }
00305 
00306 static void Swap8(size_t count, ON__UINT64* a, ON__UINT64* b)
00307 {
00308   ON__UINT64 t;
00309   while (count--)
00310   {
00311     t = *a;
00312     *a = *b;
00313     *b = t;
00314     a++;
00315     b++;
00316   }
00317 }
00318 
00319 void ON_RandomNumberGenerator::RandomPermutation(void* base, size_t nel, size_t sizeof_element )
00320 {
00321   ON__UINT32 i, j, n;
00322 
00323   if ( 0 == base || nel <= 1 || sizeof_element <= 0 )
00324     return;
00325 
00326 #if defined(ON_64BIT_POINTER)
00327   if ( nel > 0xFFFFFFFF || sizeof_element > 0xFFFFFFFF)
00328     return;
00329 #endif
00330 
00331   n = (ON__UINT32)nel; // for 64 bit systems, nel is wider than n.
00332 
00333   // References: 
00334   //  http://en.wikipedia.org/wiki/Random_permutation
00335   //  http://en.wikipedia.org/wiki/Knuth_shuffle
00336 
00337   // Note:
00338   //   There is the usual "sloppy bias" in the code below because 
00339   //   (on_random_number(&m_rand_context) % N) is used to get a random
00340   //   number int the range 0 to N-1 when N is not a factor of 2^32.
00341   //   As usual, this bias is not worth worrying about
00342   //   unlsess 2^32 / N is smallish.  If you need a random
00343   //   permuation of a very large array, look elsewhere.
00344 
00345   if ( 0 == sizeof_element % sizeof(ON__UINT64) )
00346   {
00347     ON__UINT64* a = (ON__UINT64*)base;
00348     sizeof_element /= sizeof(a[0]);
00349     for ( i = 0; i < n; i++ )
00350     {
00351       j = on_random_number(&m_rand_context) % (n-i);
00352       if ( j )
00353       {
00354         Swap8(sizeof_element, a+i, a+i+j);
00355       }
00356     }
00357   }
00358   else if ( 0 == sizeof_element % sizeof(ON__UINT32) )
00359   {
00360     ON__UINT32* a = (ON__UINT32*)base;
00361     sizeof_element /= sizeof(a[0]);
00362     for ( i = 0; i < n; i++ )
00363     {
00364       j = on_random_number(&m_rand_context) % (n-i);
00365       if ( j )
00366       {
00367         Swap4(sizeof_element, a+i, a+i+j);
00368       }
00369     }
00370   }
00371   else
00372   {
00373     unsigned char* a = (unsigned char*)base;
00374     for ( i = 0; i < n; i++ )
00375     {
00376       j = on_random_number(&m_rand_context) % (n-i);
00377       if ( j )
00378       {
00379         Swap1(sizeof_element, a+i, a+i+j);
00380       }
00381     }
00382   }
00383 }
00384 


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:27:03