Created
July 16, 2015 17:27
-
-
Save mrchnk/b24c31d3a615a412374e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Random number generator | |
// | |
/*-------------------------------------------------------------------------*/ | |
/* Coefficients used in the pure random number generator. */ | |
#define c3 15731L | |
#define c2 789221L | |
#define c1 1376312589L | |
/* Read-only, XOR masks for random # generation. */ | |
static const uint32_t Random_Xor_Masks[31] = | |
{ | |
/* First mask is for generating sequences of 3 (2^2 - 1) random numbers, | |
/ Second mask is for generating sequences of 7 (2^3 - 1) random numbers, | |
/ etc. Numbers to the right are number of bits of random number sequence. | |
/ It generates 2^n - 1 numbers. */ | |
0x00000003L, 0x00000006L, 0x0000000CL, 0x00000014L, /* 2,3,4,5 */ | |
0x00000030L, 0x00000060L, 0x000000B8L, 0x00000110L, /* 6,7,8,9 */ | |
0x00000240L, 0x00000500L, 0x00000CA0L, 0x00001B00L, /* 10,11,12,13 */ | |
0x00003500L, 0x00006000L, 0x0000B400L, 0x00012000L, /* 14,15,16,17 */ | |
0x00020400L, 0x00072000L, 0x00090000L, 0x00140000L, /* 18,19,20,21 */ | |
0x00300000L, 0x00400000L, 0x00D80000L, 0x01200000L, /* 22,23,24,25 */ | |
0x03880000L, 0x07200000L, 0x09000000L, 0x14000000L, /* 26,27,28,29 */ | |
0x32800000L, 0x48000000L, 0xA3000000L /* 30,31,32 */ | |
}; /* Randomizer Xor mask values CRK 10-29-90 */ | |
/*-------------------------------------------------------------------------*/ | |
//TRandomFast gRandomFast = { 0, 0, 0}; Initialized in global.cpp | |
/*-*------------------------------------------------------------------------- | |
/ Function | |
/ RandomFastInit | |
/ | |
/ Purpose | |
/ This initializes the fast random number generator. | |
/ | |
/ Notes | |
/ The fast random number generator has some unique qualities: | |
/ | |
/ 1) The same sequence repeats every 2^n-1 generations. | |
/ 2) Each number can be generated extremely rapidly. | |
/ | |
/ Entry | |
/ pRandomFast = Pointer to data structure for current state of a fast | |
/ pseudorandom number generator. | |
/--------------------------------------------*/ | |
void MathUtils::RandomFastInit(pTRandomFast pRandomFast) | |
{ | |
int32_t n = 31; // Changed from 32 to 31 per Prince (you mean "The Artist"?) | |
pRandomFast->uValue = (uint32_t)(VMPI_getPerformanceCounter()); | |
/* Figure out the sequence length (2^n - 1). */ | |
pRandomFast->uSequenceLength = (1L << n) - 1L; | |
/* Gather the XOR mask value. */ | |
pRandomFast->uXorMask = Random_Xor_Masks[n - 2]; | |
} | |
/*-------------------------------------------------------------------------*/ | |
/*-*------------------------------------------------------------------------- | |
/ Function | |
/ imRandomFastNext | |
/ | |
/ Purpose | |
/ This generates a new pseudorandom number using the fast random number | |
/ generator. | |
/ | |
/ Notes | |
/ The fast random number generator must be initialized before use. | |
/ | |
/ This is implemented as a macro for the best possible performance. | |
/ | |
/ Entry | |
/ pRandomFast = Pointer to data structure for current state of a fast | |
/ pseudorandom number generator. | |
/ | |
/ Exit | |
/ Returns the next pseudorandom number in the sequence. | |
/--------------------------------------------*/ | |
#define RandomFastNext(_pRandomFast) \ | |
( \ | |
((_pRandomFast)->uValue & 1L) \ | |
? ((_pRandomFast)->uValue = ((_pRandomFast)->uValue >> 1) ^ (_pRandomFast)->uXorMask) \ | |
: ((_pRandomFast)->uValue = ((_pRandomFast)->uValue >> 1)) \ | |
) | |
/*-------------------------------------------------------------------------*/ | |
/*-*------------------------------------------------------------------------- | |
/ Function | |
/ RandomPureHasher | |
/ | |
/ Purpose | |
/ This generates a pseudorandom number from a given seed using the high | |
/ quality random number generator. | |
/ | |
/ Notes | |
/ The caller must pass in a seed value. This value is typically the | |
/ output of the fast random number generator multiplied by a prime | |
/ number, but can be any seed which was not derived from the output of | |
/ this function. | |
/ | |
/ Please note that this random number generator is really as hasher. | |
/ It will not work well if you pass its own output in as the next input. | |
/ | |
/ A given input seed always generates the same pseudorandom output result. | |
/ | |
/ The feature of this hasher is that the value returned from one seed | |
/ to the next is highly uncorrelated to the seed value. High quality | |
/ multidimensional random numbers can be generated by using a sum of | |
/ prime multiples of the seed values. | |
/ | |
/ For example, to generate a vector given three seed values sx, sy and sz, | |
/ use something like the following: | |
/ result = imRandomPureHasher(59*sx + 67*sy + 71*sz); | |
/ | |
/ Entry | |
/ iSeed = Starting seed value. | |
/ | |
/ Exit | |
/ Returns the next pseudorandom value in the sequence. | |
/--------------------------------------------*/ | |
int32_t MathUtils::RandomPureHasher(int32_t iSeed) | |
{ | |
int32_t iResult; | |
/* Adapted from "A Recursive Implementation of the Perlin Noise Function," | |
/ by Greg Ward, Graphics Gems II, p. 396. */ | |
/* First, hash s as a preventive measure. This helps ensure the first | |
/ few numbers are more random when used in conjunction with the fast | |
/ random number generator, which starts off with the first 10 or so | |
/ numbers all zero in the lowe bits. */ | |
iSeed = ((iSeed << 13) ^ iSeed) - (iSeed >> 21); | |
/* Next, use a third order odd polynomial, better than linear. */ | |
iResult = (iSeed*(iSeed*iSeed*c3 + c2) + c1) & kRandomPureMax; | |
/* DJ14dec94 -- The above wonderful expression always returns odd | |
/ numbers, and this is easy to prove. So we add the seed back to | |
/ the result which again randomizes bit zero. */ | |
iResult += iSeed; | |
/* DJ17nov95 -- The above always returns values that are NEVER divisible | |
/ evenly by four, so do additional hashing. */ | |
iResult = ((iResult << 13) ^ iResult) - (iResult >> 21); | |
return iResult; | |
} | |
/* ------------------------------------------------------------------------------ */ | |
int32_t MathUtils::GenerateRandomNumber(pTRandomFast pRandomFast) | |
{ | |
// Fill out gRandomFast if it is uninitialized. | |
if (pRandomFast->uValue == 0) { | |
RandomFastInit(pRandomFast); | |
} | |
long aNum = RandomFastNext(pRandomFast); | |
/* Use the pure random number generator to hash the result. */ | |
aNum = RandomPureHasher(aNum * 71L); | |
return aNum & kRandomPureMax; | |
} | |
int32_t MathUtils::Random(int32_t range, pTRandomFast pRandomFast) | |
{ | |
if (range > 0) { | |
return GenerateRandomNumber(pRandomFast) % range; | |
} else { | |
return 0; | |
} | |
} | |
void MathUtils::initRandom(TRandomFast *seed) | |
{ | |
RandomFastInit(seed); | |
} | |
double MathUtils::random(TRandomFast *seed) | |
{ | |
return (double)GenerateRandomNumber(seed) / ((double)kRandomPureMax+1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment