- 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:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user