random value on Twister class

Started by
1 comment, last by Helicobster 14 years, 1 month ago
Hi, i need help translating a class, i hope you guys dont mind i put the whole code in here. honestly speaking i dont understand what it did from top to bottom but i know the intention is to build a random value. the problem is i dont know if this random has some kind of constraint or its pure random. so im trying to build a ray tracing program. one of the purpose is to create a random value to create the ray, some kind of random sampling. if you follow this link: http://www.devmaste r.net/articles/ raytracing_ series/part5. php you'll find the explanation about the function used in one of the sniplet (the diffuse reflection subtopic). its the Twister.cpp file. all i need to know is if the value generated to some value or its pure random so i can replace it by c++ random function or there are some kind of constraints to the random value hope i did not ask too much :) many thanks in advance here is the code in the class


#include<math.h>
#include<stdlib.h>

#include"twister. h"

namespace Raytracer {

unsigned short mtRand_xsubi[ 3] = { 723, 32761, 44444 };

#define M 397
#define MATRIX_A 0x9908b0df
#define UPPER_MASK 0x80000000
#define LOWER_MASK 0x7fffffff

#define TEMPERING_MASK_ B 0x9d2c5680
#define TEMPERING_MASK_ C 0xefc60000
#define TEMPERING_SHIFT_ U(y)  (y >> 11)
#define TEMPERING_SHIFT_ S(y)  (y << 7)
#define TEMPERING_SHIFT_ T(y)  (y << 15)
#define TEMPERING_SHIFT_ L(y)  (y >> 18)

void Twister::Seed( unsigned long seed )
{
    mt[0]= seed & 0xffffffff;
    for ( mti = 1; mti < mtRand_N; mti++ ) mt[mti] = (69069 * mt[mti - 1]) & 0xffffffff;
    unsigned long s = 373737;
    for ( mti = 1; mti < mtRand_N; mti++ )
    {
		mt[mti] ^= s;
		s = s * 5531 + 81547;
		s ^= (s >> 9) ^ (s << 19);
    }
}

float Twister::Rand( )
{
    unsigned long y;
    static unsigned long mag01[2] = {0x0, MATRIX_A};
    if (mti >= mtRand_N) 
	{
        int kk;
        for (kk=0;kk<mtRand_N-M;kk+ +) 
		{
            y = (mt[kk]&UPPER_MASK)| (mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
        }
        for (;kk<mtRand_N-1;kk+ +) 
		{
            y = (mt[kk]&UPPER_MASK)| (mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-mtRand_ N)] ^ (y >> 1) ^ mag01[y & 0x1];
        }
        y = (mt[mtRand_N- 1]&UPPER_MASK)| (mt[0]&LOWER_MASK);
        mt[mtRand_N- 1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
        mti = 0;
    }
    y = mt[mti++];
    y ^= TEMPERING_SHIFT_ U(y);
    y ^= TEMPERING_SHIFT_ S(y) & TEMPERING_MASK_ B;
    y ^= TEMPERING_SHIFT_ T(y) & TEMPERING_MASK_ C;
    y ^= TEMPERING_SHIFT_ L(y);
    return ( (float)y * 2.3283064370807974e -10f );
}

unsigned long Twister::RandL( )
{
    unsigned long y;
    static unsigned long mag01[2] = { 0x0, MATRIX_A };
    if (mti >= mtRand_N) 
	{
        int kk;
        for (kk=0;kk<mtRand_N-M;kk+ +) 
		{
            y = (mt[kk]&UPPER_MASK)| (mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
        }
        for (;kk<mtRand_N-1;kk+ +) 
		{
            y = (mt[kk]&UPPER_MASK)| (mt[kk+1]&LOWER_MASK);
            mt[kk] = mt[kk+(M-mtRand_ N)] ^ (y >> 1) ^ mag01[y & 0x1];
        }
        y = (mt[mtRand_N- 1]&UPPER_MASK)| (mt[0]&LOWER_MASK);
        mt[mtRand_N- 1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
        mti = 0;
    }
    y = mt[mti++];
    y ^= TEMPERING_SHIFT_ U(y);
    y ^= TEMPERING_SHIFT_ S(y) & TEMPERING_MASK_ B;
    y ^= TEMPERING_SHIFT_ T(y) & TEMPERING_MASK_ C;
    y ^= TEMPERING_SHIFT_ L(y);
    return y;
}

}; // namespace Raytracer

Advertisement
`2.3283064370807974e -10f' should be `2.3283064370807974e-10f'.

You probably mean to ask if the number returned follows a uniform distribution, and the answer is "yes".

Yes, you can replace that Mersenne Twister random number generator with the basic C++ random number generator, but the Mersenne Twister generally offers better performance and better randomness, which is why it's used in that Devmaster tutorial in the first place.

If you were to rely on rand() to jitter samples in your raytracer (or to do anything else that requires a lot of random numbers), you'd eventually notice unnatural-looking patterns.

If the Mersenne Twister is working in your raytracer, you might as well keep using it, even if you don't understand its workings. If you could intuitively understand what it was doing, it wouldn't be much of a random number generator, would it?

This topic is closed to new replies.

Advertisement