diff --git a/source/backend/parser/express.cpp b/source/backend/parser/express.cpp index cd47faf..d32d632 100644 --- a/source/backend/parser/express.cpp +++ b/source/backend/parser/express.cpp @@ -1113,7 +1113,7 @@ void Parser::Parse_Num_Factor (EXPRESS Express,int *Terms) i = (int)Parse_Float_Param(); if ((i < 0) || (i >= Number_Of_Random_Generators)) Error("Illegal random number generator."); - Val = stream_rand(i); + Val = stream_rand(&next_rand[i]); break; case DIMENSIONS_TOKEN: @@ -3485,6 +3485,36 @@ void Parser::POV_strlwr(char *s) } } +#define ROTATE(v,c) (((v) << (c)) | ((v) >> (32 - (c)))) +#define XOR(v,w) ((v) ^ (w)) +#define PLUS(v,w) (((v) + (w))) +#define PLUSONE(v) (PLUS((v),1)) + +#define QUARTERROUND(a,b,c,d) \ + x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ + x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ + x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ + x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); + +void Parser::chacha(uint32_t *output32, uint32_t *input32) +{ + int i; + uint32_t x[16]; + + for (i = 0;i < 16;++i) x[i] = input32[i]; + for (i = 8;i > 0;i -= 2) { + QUARTERROUND( 0, 4, 8,12) + QUARTERROUND( 1, 5, 9,13) + QUARTERROUND( 2, 6,10,14) + QUARTERROUND( 3, 7,11,15) + QUARTERROUND( 0, 5,10,15) + QUARTERROUND( 1, 6,11,12) + QUARTERROUND( 2, 7, 8,13) + QUARTERROUND( 3, 4, 9,14) + } + for (i = 0;i < 16;++i) x[i] = PLUS(x[i],input32[i]); + for (i = 0;i < 16;++i) output32[i] = x[i]; +} /***************************************************************************** * @@ -3494,7 +3524,7 @@ void Parser::POV_strlwr(char *s) * * INPUT * -* stream - number of random stream +* stream - pointer to next_rand_t struct * * OUTPUT * @@ -3517,11 +3547,15 @@ void Parser::POV_strlwr(char *s) * ******************************************************************************/ -DBL Parser::stream_rand(int stream) +DBL Parser::stream_rand(next_rand_t *nr) { - next_rand[stream] = next_rand[stream] * 1812433253L + 12345L; + if (nr->nrints == 0) { + if (!++nr->in[12]) if (!++nr->in[13]) if (!++nr->in[14]) ++nr->in[15]; + chacha(nr->out, nr->in); + nr->nrints = 16; + } - return((DBL)(next_rand[stream] & 0xFFFFFFFFUL) / 0xFFFFFFFFUL); + return((DBL)(nr->out[--nr->nrints]) * (DBL)0.00000000023283064365386962890625); } @@ -3546,7 +3580,7 @@ DBL Parser::stream_rand(int stream) * * DESCRIPTION * -* Set start value for pseudo-random generator. +* Allocate a new generator and set start value for pseudo-random generator. * * CHANGES * @@ -3556,12 +3590,31 @@ DBL Parser::stream_rand(int stream) int Parser::stream_seed(int seed) { - next_rand = (unsigned int *)POV_REALLOC(next_rand, (Number_Of_Random_Generators+1)*sizeof(unsigned int), "random number generator"); - - next_rand[Number_Of_Random_Generators] = (unsigned int)seed; + next_rand_t *nr; + + next_rand = (next_rand_t*)POV_REALLOC(next_rand, + (Number_Of_Random_Generators+1)*sizeof(next_rand_t), + "random number generator"); + nr = &next_rand[Number_Of_Random_Generators]; + nr->nrints = 0; + nr->in[0] = 0x736e6f63; + nr->in[1] = 0x746e6174; + nr->in[2] = 0x72616720; + nr->in[3] = 0x65676162; + nr->in[4] = 0xc0ffee; + nr->in[5] = seed; + nr->in[6] = seed ^ 0xbeef; + nr->in[7] = 0xbabe; + nr->in[8] = 20120608; + nr->in[9] = 0; + nr->in[10] = 0; + nr->in[11] = 0; + nr->in[12] = 0; + nr->in[13] = 0; + nr->in[14] = 0; + nr->in[15] = 0; Number_Of_Random_Generators++; - return (Number_Of_Random_Generators-1); } diff --git a/source/backend/parser/parse.h b/source/backend/parser/parse.h index ec5fdd3..b004290 100644 --- a/source/backend/parser/parse.h +++ b/source/backend/parser/parse.h @@ -216,6 +216,12 @@ enum }; +typedef struct { + uint32_t in[16]; + uint32_t out[16]; + int nrints; +} next_rand_t; + /***************************************************************************** * Global typedefs ******************************************************************************/ @@ -577,7 +583,8 @@ class Parser : public Task // express.h/express.cpp short Have_Vector; unsigned int Number_Of_Random_Generators; - unsigned int *next_rand; + next_rand_t *next_rand; + void chacha(uint32_t *, uint32_t *); bool Allow_Identifier_In_Call, Identifier_In_Call; @@ -742,7 +749,7 @@ class Parser : public Task void POV_strupr (char *s); void POV_strlwr (char *s); - DBL stream_rand (int stream); + DBL stream_rand (next_rand_t*); int stream_seed (int seed); // fnsyntax.h/fnsyntax.cpp