Search the web
Sign In
New User? Sign Up
csound--maths.ex.ac.uk
? Already a member? Sign in to Yahoo!

Yahoo! Groups Tips

Did you know...
Show off your group to the world. Share a photo of your group with us.

Best of Y! Groups

   Check them out and nominate your group.
Having problems with message search? Fill out this form to ensure your group is one of the first to be migrated to the new message search system.

Messages

  Messages Help
Advanced
[Csnd] 31 bit pseudo-random number gen in C, C++ & dsPIC assembly c   Message List  
Reply | Forward Message #34779 of 47297 |
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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>

#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@...



Tue Sep 27, 2005 11:11 pm

istvan_v@...
Send Email Send Email

Forward
Message #34779 of 47297 |
Expand Messages Author Sort by Date

Hi Csounders! I haven't been doing anything with Csound in recent years, but I lurk on this list. Nearly 10 years ago I contributed a 31 bit pseudo-random ...
Robin Whittle
rw@...
Send Email
Sep 21, 2005
5:14 pm

... Do you mean the x = (x * 16807) % 0x7FFFFFFF algorithm ? It is actually used in some newer opcodes as well. In fact, I think using rand() is a bad idea for...
Istvan Varga
istvan_v@...
Send Email
Sep 22, 2005
8:53 am

Hi, I'm using Csound for some audio signal processing work. I'd like to use the "display" opcode to show some variable values. The problem I'm having is that...
Chris Share
cshare01@...
Send Email
Sep 22, 2005
10:07 am

what version of csound are you using? [ i use display opcode a lot in MacCsound ] -m ... -- Send bugs reports to this list. To unsubscribe, send email to...
Matt J. Ingalls
ingalls@...
Send Email
Sep 22, 2005
11:38 pm

Hi Istvan, ... This is probably the best known linear congruential PRNG - Park and Miller's "minimal standard" from 1988. What was not so clear was how to...
Robin Whittle
rw@...
Send Email
Sep 22, 2005
11:31 am

No division is needed. Just clear the high order bit if it is set using an and. Also you need to ignore the constant setting of the overflow bit. If you dont...
Michael Rempel
michael_rempel@...
Send Email
Sep 22, 2005
2:59 pm

How efficient is the Whittle algorithm compared to the Mersenne Twister? And, how random is it? The MT has become the standard high-performance pseudo-random...
Michael Gogins
gogins@...
Send Email
Sep 22, 2005
2:21 pm

It is not as random as the Mersenne Twister. The period is much smaller, and there is serial correlation between successive outputs. There are some other ...
jlato@...
Send Email
Sep 22, 2005
3:44 pm

Argh. I fell victim to the same error as Michel, and I said in my post that it's 31-bit. Thanks, Istvan. Anyway, if it were mod(2^32), it would definately be...
jlato@...
Send Email
Sep 22, 2005
3:51 pm

... Its not my algorithm - its David G. Carta's. The properly commented code is here: http://www.firstpr.com.au/dsp/rand31/rand31-park-miller-carta-int.c.txt...
Robin Whittle
rw@...
Send Email
Sep 23, 2005
9:46 am

... Actually, it is faster, at least on x86 with GCC, because the compiler can take advantage of the fact that 32 bit multiplication always produces a 64 bit...
Istvan Varga
istvan_v@...
Send Email
Sep 23, 2005
12:11 pm

Hi Istvan, I have never tried looking at the assembly code generated from C-code like this. I imagine a 32 x 32 multiply takes more CPU cycles than a 16 x 16...
Robin Whittle
rw@...
Send Email
Sep 23, 2005
12:45 pm

... No, your code compiles to 32 bit multiplies even if I add explicit casts to 16 bit types (perhaps because a 32 bit multiplication is actually faster than a...
Istvan Varga
istvan_v@...
Send Email
Sep 23, 2005
1:13 pm

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. ...
Istvan Varga
istvan_v@...
Send Email
Sep 27, 2005
11:15 pm

Thanks Istvan for these timing results. What CPU and clock rate were you using? Andrew Simper, on the Music-DSP mailing list ( ...
Robin Whittle
rw@...
Send Email
Sep 29, 2005
2:06 am

... A rather old Pentium III (Celeron) 1300 MHz. ... Thanks for this tip, it seems to work well, so I will use it. ... Yes, as far as the trick to avoid using...
Istvan Varga
istvan_v@...
Send Email
Sep 29, 2005
11:42 am

... This is wrong. Note that the algorithm is x = (x * 16807) % 0x7FFFFFFF and not x = (x * 16807) & 0x7FFFFFFF Here is a fast (well, at least on x86) version...
Istvan Varga
istvan_v@...
Send Email
Sep 22, 2005
2:59 pm

mod gives the same result as and. The division is perfect binary. tt is the reason 0x7FFFFFFF is choosen. You can do the same thing for any power of 2...
Michael Rempel
michael_rempel@...
Send Email
Sep 22, 2005
3:30 pm

In the line tmp2 = (uint32_t) tmp1 & (uint32_t) 0x7FFFFFFF; what does the & operator do? In C it is an address operator, which makes no sense. In C++ it is...
Michael Rempel
michael_rempel@...
Send Email
Sep 22, 2005
3:34 pm

... In C it is bitwise AND as well, but note the other lines that correct the result so that it will be the same as if % was used, assuming that the input...
Istvan Varga
istvan_v@...
Send Email
Sep 22, 2005
3:51 pm

Nope. It is the bitwise AND in both languages (C++ supports all of C as a subset). && is logical AND. & is also the address-of operator in both languages; as...
Richard Dobson
richarddobson@...
Send Email
Sep 22, 2005
3:56 pm

Thanks. It has been a while since I used c/c++. I use Delphi most of the time. cheers, Michael ... From: Richard Dobson [mailto:richarddobson@...]...
Michael Rempel
michael_rempel@...
Send Email
Sep 22, 2005
3:58 pm

Still wrong. Note that the mod is not by 0x80000000 (which could really be replaced with a simple AND), but one less and that is not so simple. I know the...
Istvan Varga
istvan_v@...
Send Email
Sep 22, 2005
3:26 pm

Yes, now we understand each other. I was simplifying. We know that x mod y is approximately x mod (y-1) for very big y values, the messing with bits after the...
Michael Rempel
michael_rempel@...
Send Email
Sep 22, 2005
3:51 pm

Fantastic! Thanks, Mike ... From: "Istvan Varga" <istvan_v@...> To: <csound@...> Sent: Tuesday, September 27, 2005 7:11 PM Subject: Re:...
Michael Gogins
gogins@...
Send Email
Sep 28, 2005
12:53 am
Advanced

Copyright © 2009 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Guidelines - Help