Csound Csound-dev Csound-tekno Search About

Re: [Csnd] 31 bit pseudo-random number gen in C, C++ & dsPIC assembly code

Date2005-09-28 01:53
From"Michael Gogins"
SubjectRe: [Csnd] 31 bit pseudo-random number gen in C, C++ & dsPIC assembly code
Fantastic!

Thanks,
Mike

----- Original Message ----- 
From: "Istvan Varga" 
To: 
Sent: Tuesday, September 27, 2005 7:11 PM
Subject: Re: [Csnd] 31 bit pseudo-random number gen in C, C++ & dsPIC 
assembly code


> Here is a comparison of the time it takes to generate 100,000,000 random
> numbers with three different generators, compiled with various compilers
> on Linux.
>
> rand31: linear congruential generator (m = 0x7FFFFFFF, a = 742938285)
> rand:   ANSI C rand()
>         (note that it is much slower if not compiled with -static)
> MT:     Mersenne Twister (MT19937)
>
> ------------------------------------------------------------------------
>
> GCC 4.1 beta (-O2 -march=pentium3 -static)
>
>   rand31: 1.703, rand: 4.559, MT: 2.501
>
> GCC 4.1 beta (-O2 -march=pentium3 -fomit-frame-pointer -static)
>
>   rand31: 1.731, rand: 4.561, MT: 2.321
>
> GCC 4.1 beta (-O2 -march=pentium3)
>
>   rand31: 1.702, rand: 7.004, MT: 2.500
>
> GCC 4.0.0 (-O2 -march=pentium3 -static)
>
>   rand31: 1.702, rand: 4.561, MT: 2.405
>
> GCC 4.0.0 (-O2 -march=pentium3 -fomit-frame-pointer -static)
>
>   rand31: 1.732, rand: 4.562, MT: 2.339
>
> GCC 3.3.4 (-O2 -march=pentium3 -static)
>
>   rand31: 1.863, rand: 4.172, MT: 2.579
>
> GCC 3.3.4 (-O2 -march=pentium3 -fomit-frame-pointer -static)
>
>   rand31: 1.730, rand: 4.172, MT: 2.385
>
> ICC 9.0 (-O2 -xK -static)
>
>   rand31: 1.841, rand: 4.410, MT: 2.474
>
> ------------------------------------------------------------------------
>
> #include 
> #include 
> #include 
> #include 
>
> #define CS_PURE __attribute__ ((__pure__))
> #define CS_NOINLINE __attribute__ ((__noinline__))
> #define PUBLIC
>
> typedef struct CsoundRandMTState_ {
>     int         mti;
>     uint32_t    mt[624];
> } CsoundRandMTState;
>
> PUBLIC CS_PURE int csoundRand31(int seedVal)
> {
>     uint64_t  tmp1;
>     uint32_t  tmp2;
>
>     /* x = (742938285 * x) % 0x7FFFFFFF */
>     tmp1 = (uint64_t) ((int32_t) seedVal * (int64_t) 742938285);
>     tmp2 = (uint32_t) tmp1 & (uint32_t) 0x7FFFFFFF;
>     tmp2 += (uint32_t) (tmp1 >> 31);
>     if ((int32_t) tmp2 < (int32_t) 0)
>       tmp2 = (tmp2 + (uint32_t) 1) & (uint32_t) 0x7FFFFFFF;
>     return (int) tmp2;
> }
>
> /* Period parameters */
>
> #define N           624
> #define M           397
> #define MATRIX_A    0x9908B0DFU     /* constant vector a */
> #define UPPER_MASK  0x80000000U     /* most significant w-r bits */
> #define LOWER_MASK  0x7FFFFFFFU     /* least significant r bits */
>
> /* initializes mt[N] with a seed */
>
> PUBLIC void csoundSeedRandMT(CsoundRandMTState *p, uint32_t seedVal)
> {
>     int       i;
>     uint32_t  x;
>
>     p->mt[0] = x = seedVal;
>     for (i = 1; i < N; i++) {
>       /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
>       /* In the previous versions, MSBs of the seed affect   */
>       /* only MSBs of the array mt[].                        */
>       /* 2002/01/09 modified by Makoto Matsumoto             */
>       x = ((uint32_t) 1812433253 * (x ^ (x >> 30)) + (uint32_t) i);
>       p->mt[i] = x;
>     }
>     p->mti = N;
> }
>
> static CS_NOINLINE void MT_update_state(CsoundRandMTState *p)
> {
>     /* mag01[x] = x * MATRIX_A  for x=0,1 */
>     const uint32_t  mag01[2] = { (uint32_t) 0, (uint32_t) MATRIX_A };
>     int       i;
>     uint32_t  y;
>     for (i = 0; i < (N - M); i++) {
>       y = (p->mt[i] & UPPER_MASK) | (p->mt[i + 1] & LOWER_MASK);
>       p->mt[i] = p->mt[i + M] ^ (y >> 1) ^ mag01[y & (uint32_t) 1];
>     }
>     for ( ; i < (N - 1); i++) {
>       y = (p->mt[i] & UPPER_MASK) | (p->mt[i + 1] & LOWER_MASK);
>       p->mt[i] = p->mt[i + (M - N)] ^ (y >> 1) ^ mag01[y & (uint32_t) 1];
>     }
>     y = (p->mt[N - 1] & UPPER_MASK) | (p->mt[0] & LOWER_MASK);
>     p->mt[N - 1] = p->mt[M - 1] ^ (y >> 1) ^ mag01[y & (uint32_t) 1];
> }
>
> /* generates a random number on [0,0xffffffff]-interval */
>
> PUBLIC uint32_t csoundRandMT(CsoundRandMTState *p)
> {
>     int       i = p->mti;
>     uint32_t  y;
>
>     if (i >= N) {                   /* generate N words at one time */
>       MT_update_state(p);
>       i = 0;
>     }
>     y = p->mt[i];
>     p->mti = i + 1;
>     /* Tempering */
>     y ^= (y >> 11);
>     y ^= (y << 7) & (uint32_t) 0x9D2C5680U;
>     y ^= (y << 15) & (uint32_t) 0xEFC60000U;
>     y ^= (y >> 18);
>
>     return y;
> }
>
> volatile uint32_t seed_;
>
> int main(void)
> {
>     CsoundRandMTState st;
>     double t0, t1, t2, t3;
>     struct timeval tv;
>     int i;
>
>     gettimeofday(&tv, NULL);
>     t0 = (double) tv.tv_usec * 0.000001 + (double) tv.tv_sec;
>     seed_ = 12345;
>     for (i = 0; i < 100000000; i++)
>       seed_ = csoundRand31(seed_);
>     gettimeofday(&tv, NULL);
>     t1 = (double) tv.tv_usec * 0.000001 + (double) tv.tv_sec;
>     srand(314159);
>     for (i = 0; i < 100000000; i++)
>       seed_ = rand();
>     gettimeofday(&tv, NULL);
>     t2 = (double) tv.tv_usec * 0.000001 + (double) tv.tv_sec;
>     csoundSeedRandMT(&st, 5489);
>     for (i = 0; i < 100000000; i++) {
>       seed_ = csoundRandMT(&st);
> /*    if (i < 500) {
>         printf("%10u ", seed_);
>         if ((i % 5) == 4) printf("\n");
>       } */
>     }
>     gettimeofday(&tv, NULL);
>     t3 = (double) tv.tv_usec * 0.000001 + (double) tv.tv_sec;
>     printf("rand31: %.3f, rand: %.3f, MT: %.3f\n",
>            (t1 - t0), (t2 - t1), (t3 - t2));
>     return 0;
> }
> -- 
> Send bugs reports to this list.
> To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk
> 


-- 
Send bugs reports to this list.
To unsubscribe, send email to csound-unsubscribe@lists.bath.ac.uk