- added RNG abstract random object rng_{new/free/seed/get{Int,Double,Float}}

to avoid use of global generator. at the moment the renderer owns the
   number generator and this is important for retaining render consistency.
This commit is contained in:
Daniel Dunbar
2005-07-25 20:33:10 +00:00
parent cb988ff8a9
commit 40a5ed791d
2 changed files with 93 additions and 55 deletions

View File

@@ -36,6 +36,21 @@
#ifndef BLI_RAND_H
#define BLI_RAND_H
/* RNG is just an abstract random number generator
* type that avoids using globals, otherwise identical
* to BLI_rand functions below.
*/
struct RNG;
struct RNG* rng_new (unsigned int seed);
void rng_free (struct RNG* rng);
void rng_seed (struct RNG* rng, unsigned int seed);
int rng_getInt (struct RNG* rng);
double rng_getDouble (struct RNG* rng);
float rng_getFloat (struct RNG* rng);
void rng_shuffleArray(struct RNG *rng, void *data, int elemSize, int numElems);
/** Seed the random number generator */
void BLI_srand (unsigned int seed);
@@ -55,17 +70,10 @@ float BLI_frand (void);
*/
void BLI_fillrand (void *addr, int len);
/** Stores the BLI randum number generator state
* into the buffer in @a loc_r.
/** Shuffle an array randomly using the given seed.
* contents. This routine does not use nor modify
* the state of the BLI random number generator.
*/
void BLI_storerand (unsigned int loc_r[2]);
/** Retores the BLI randum number generator state
* from the buffer in @a loc.
*/
void BLI_restorerand (unsigned int loc[2]);
/** Shuffle an array randomly using the given seed. */
void BLI_array_randomize (void *data, int elemSize, int numElems, unsigned int seed);
#endif

View File

@@ -33,6 +33,8 @@
#include <stdlib.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "PIL_time.h"
#include "BLI_rand.h"
@@ -51,57 +53,50 @@ typedef unsigned long long r_uint64;
#define LOWSEED 0x330E
static r_uint64 X= 0;
/***/
void BLI_srand(unsigned int seed) {
X= (((r_uint64) seed)<<16) | LOWSEED;
}
typedef struct RNG {
r_uint64 X;
} RNG;
int BLI_rand(void) {
X= (MULTIPLIER*X + ADDEND)&0x0000FFFFFFFFFFFF;
return (int) (X>>17);
}
double BLI_drand(void) {
return (double) BLI_rand()/0x80000000;
}
float BLI_frand(void) {
return (float) BLI_rand()/0x80000000;
}
void BLI_storerand(unsigned int loc_r[2]) {
loc_r[0]= (unsigned int) (X>>32);
loc_r[1]= (unsigned int) (X&0xFFFFFFFF);
}
void BLI_restorerand(unsigned int loc[2]) {
X= ((r_uint64) loc[0])<<32;
X|= loc[1];
}
void BLI_fillrand(void *addr, int len) {
unsigned char *p= addr;
unsigned int save[2];
BLI_storerand(save);
BLI_srand((unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF));
while (len--) *p++= BLI_rand()&0xFF;
BLI_restorerand(save);
}
void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed)
RNG *rng_new(unsigned int seed)
{
RNG *rng = MEM_mallocN(sizeof(*rng), "rng");
rng_seed(rng, seed);
return rng;
}
void rng_free(RNG* rng)
{
MEM_freeN(rng);
}
void rng_seed(RNG *rng, unsigned int seed) {
rng->X= (((r_uint64) seed)<<16) | LOWSEED;
}
int rng_getInt(RNG *rng) {
rng->X= (MULTIPLIER*rng->X + ADDEND)&0x0000FFFFFFFFFFFF;
return (int) (rng->X>>17);
}
double rng_getDouble(RNG *rng) {
return (double) rng_getInt(rng)/0x80000000;
}
float rng_getFloat(RNG *rng) {
return (float) rng_getInt(rng)/0x80000000;
}
void rng_shuffleArray(RNG *rng, void *data, int elemSize, int numElems)
{
unsigned int oldrand[2];
int i = numElems;
void *temp = malloc(elemSize);
BLI_storerand(oldrand);
BLI_srand(seed);
while (--i) {
int j = BLI_rand()%i;
int j = rng_getInt(rng)%i;
void *iElem = (unsigned char*)data + i*elemSize;
void *jElem = (unsigned char*)data + j*elemSize;
@@ -110,7 +105,42 @@ void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int se
memcpy(jElem, temp, elemSize);
}
BLI_restorerand(oldrand);
free(temp);
}
/***/
static RNG theBLI_rng = {0};
void BLI_srand(unsigned int seed) {
rng_seed(&theBLI_rng, seed);
}
int BLI_rand(void) {
return rng_getInt(&theBLI_rng);
}
double BLI_drand(void) {
return rng_getDouble(&theBLI_rng);
}
float BLI_frand(void) {
return rng_getFloat(&theBLI_rng);
}
void BLI_fillrand(void *addr, int len) {
RNG rng;
unsigned char *p= addr;
rng_seed(&rng, (unsigned int) (PIL_check_seconds_timer()*0x7FFFFFFF));
while (len--) *p++= rng_getInt(&rng)&0xFF;
}
void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed)
{
RNG rng;
rng_seed(&rng, seed);
rng_shuffleArray(&rng, data, elemSize, numElems);
}