--- projs/trunk/shared_source/c_datd/esrg_rand_int.c 2016/11/05 10:55:22 70 +++ projs/trunk/shared_source/c_datd/esrg_rand_int.c 2016/11/05 11:07:06 71 @@ -1,195 +1,195 @@ -//$Header$ -//------------------------------------------------------------------------------------------------- -//This file is part of "David T. Ashley's Shared Source Code", a set of shared components -//integrated into many of David T. Ashley's projects. -//------------------------------------------------------------------------------------------------- -//This source code and any program in which it is compiled/used is provided under the MIT License, -//reproduced below. -//------------------------------------------------------------------------------------------------- -//Permission is hereby granted, free of charge, to any person obtaining a copy of -//this software and associated documentation files(the "Software"), to deal in the -//Software without restriction, including without limitation the rights to use, -//copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the -//Software, and to permit persons to whom the Software is furnished to do so, -//subject to the following conditions : -// -//The above copyright notice and this permission notice shall be included in all -//copies or substantial portions of the Software. -// -//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -//SOFTWARE. -//------------------------------------------------------------------------------------------------- -#define MODULE_ESRG_RAND_INT - -#include -#include -#include - -#include "esrg_rand_int.h" -#include "intfunc.h" - - -void ESRG_RAND_INT_Alg01_Init(struct ESRG_RAND_INT_Alg01RngState *state, - int init_val) - { - int i; - - assert(state != NULL); - assert((init_val==-1) || (init_val>0)); - - //Regardless of init type, zero out the structure. Among other things, - //this sets the number of remaining random bits to zero. - memset(state, 0, sizeof(*state)); - - if (init_val == -1) - { - //This is the system randomness initialization case. Some value - //of system time should be adequate to start with. - state->rn_seed_whole = time(NULL); - state->rn_seed_fractional = time(NULL); - - //Flip a few bits in the seeds to hopefully make them different - //(but it doesn't matter if they aren't). - state->rn_seed_whole ^= 0xA5A5A5A5; - state->rn_seed_fractional ^= 0x5A5A5A5A; - - //Be absolutely sure that the seeds can't be zero. - state->rn_seed_whole |= 0x1; - state->rn_seed_fractional |= 0x2; - - //Iterate a small number of times to add further randomness - //to the two seeds. - for (i=0; i<3; i++) - { - state->rn_seed_whole - = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_whole); - } - - for (i=0; i<7; i++) - { - state->rn_seed_fractional - = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_fractional); - } - } - else - { - //This is the branch where the random seed is supplied. We can - //use very much the same approach as above to try to get something - //random. - state->rn_seed_whole = init_val; - state->rn_seed_fractional = init_val; - - //Flip a few bits in the seeds to hopefully make them different - //(but it doesn't matter if they aren't). - state->rn_seed_whole ^= 0xA5A5A5A5; - state->rn_seed_fractional ^= 0x5A5A5A5A; - - //Be absolutely sure that the seeds can't be zero. - state->rn_seed_whole |= 0x1; - state->rn_seed_fractional |= 0x2; - - //Iterate a small number of times to add further randomness - //to the two seeds. - for (i=0; i<3; i++) - { - state->rn_seed_whole - = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_whole); - } - - for (i=0; i<7; i++) - { - state->rn_seed_fractional - = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_fractional); - } - } - - //At this point the state is randomized. The number of bits valid - //in the bit reservoir is set to zero, so will force a restock - //next time. - } - - -//Restocks the bit reservoir. -static void ESRG_RAND_INT_Alg01_RestockBitBuffer( - struct ESRG_RAND_INT_Alg01RngState *state - ) - { - assert(state != NULL); - - //We need to keep chugging along until we get an integer with the top two - //bits clear. This is the only way to get a random distribution of bits. - do - { - assert(state->rn_seed_fractional != 0); - state->rn_seed_fractional - = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_fractional); - } while (state->rn_seed_fractional & 0xC0000000); - - //At this point the lower 30 bits should be random. - state->bit_buffer = state->rn_seed_fractional; - state->n_bb_valid = 30; - } - - -unsigned int ESRG_RAND_INT_Alg01_RandomBit( - struct ESRG_RAND_INT_Alg01RngState *state - ) - { - int rv; - - assert(state != NULL); - - //Restock the supply of bits if necessary. - if (state->n_bb_valid == 0) - ESRG_RAND_INT_Alg01_RestockBitBuffer(state); - - if (state->bit_buffer & 0x01) - rv = 1; - else - rv = 0; - - state->bit_buffer >>= 1; - state->n_bb_valid--; - - return(rv); - } - - -unsigned int ESRG_RAND_INT_Alg01_RandomByte( - struct ESRG_RAND_INT_Alg01RngState *state - ) - { - int rv; - - assert(state != NULL); - - //Be sure enough bits to yank a byte. - if (state->n_bb_valid < 8) - ESRG_RAND_INT_Alg01_RestockBitBuffer(state); - - //Grab the byte and return. - rv = state->bit_buffer & 0xFF; - state->bit_buffer >>= 8; //Must roll down to get new set of bits. - state->n_bb_valid -= 8; - - return(rv); - } - - -const char *ESRG_RAND_INT_cvcinfo(void) - { - return("$Header$"); - } - - -const char *ESRG_RAND_INT_hvcinfo(void) - { - return(ESRG_RAND_INT_H_VERSION); - } - -//End of esrg_rand_int.c. +//$Header$ +//------------------------------------------------------------------------------------------------- +//This file is part of "David T. Ashley's Shared Source Code", a set of shared components +//integrated into many of David T. Ashley's projects. +//------------------------------------------------------------------------------------------------- +//This source code and any program in which it is compiled/used is provided under the MIT License, +//reproduced below. +//------------------------------------------------------------------------------------------------- +//Permission is hereby granted, free of charge, to any person obtaining a copy of +//this software and associated documentation files(the "Software"), to deal in the +//Software without restriction, including without limitation the rights to use, +//copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the +//Software, and to permit persons to whom the Software is furnished to do so, +//subject to the following conditions : +// +//The above copyright notice and this permission notice shall be included in all +//copies or substantial portions of the Software. +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +//SOFTWARE. +//------------------------------------------------------------------------------------------------- +#define MODULE_ESRG_RAND_INT + +#include +#include +#include + +#include "esrg_rand_int.h" +#include "intfunc.h" + + +void ESRG_RAND_INT_Alg01_Init(struct ESRG_RAND_INT_Alg01RngState *state, + int init_val) + { + int i; + + assert(state != NULL); + assert((init_val==-1) || (init_val>0)); + + //Regardless of init type, zero out the structure. Among other things, + //this sets the number of remaining random bits to zero. + memset(state, 0, sizeof(*state)); + + if (init_val == -1) + { + //This is the system randomness initialization case. Some value + //of system time should be adequate to start with. + state->rn_seed_whole = time(NULL); + state->rn_seed_fractional = time(NULL); + + //Flip a few bits in the seeds to hopefully make them different + //(but it doesn't matter if they aren't). + state->rn_seed_whole ^= 0xA5A5A5A5; + state->rn_seed_fractional ^= 0x5A5A5A5A; + + //Be absolutely sure that the seeds can't be zero. + state->rn_seed_whole |= 0x1; + state->rn_seed_fractional |= 0x2; + + //Iterate a small number of times to add further randomness + //to the two seeds. + for (i=0; i<3; i++) + { + state->rn_seed_whole + = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_whole); + } + + for (i=0; i<7; i++) + { + state->rn_seed_fractional + = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_fractional); + } + } + else + { + //This is the branch where the random seed is supplied. We can + //use very much the same approach as above to try to get something + //random. + state->rn_seed_whole = init_val; + state->rn_seed_fractional = init_val; + + //Flip a few bits in the seeds to hopefully make them different + //(but it doesn't matter if they aren't). + state->rn_seed_whole ^= 0xA5A5A5A5; + state->rn_seed_fractional ^= 0x5A5A5A5A; + + //Be absolutely sure that the seeds can't be zero. + state->rn_seed_whole |= 0x1; + state->rn_seed_fractional |= 0x2; + + //Iterate a small number of times to add further randomness + //to the two seeds. + for (i=0; i<3; i++) + { + state->rn_seed_whole + = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_whole); + } + + for (i=0; i<7; i++) + { + state->rn_seed_fractional + = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_fractional); + } + } + + //At this point the state is randomized. The number of bits valid + //in the bit reservoir is set to zero, so will force a restock + //next time. + } + + +//Restocks the bit reservoir. +static void ESRG_RAND_INT_Alg01_RestockBitBuffer( + struct ESRG_RAND_INT_Alg01RngState *state + ) + { + assert(state != NULL); + + //We need to keep chugging along until we get an integer with the top two + //bits clear. This is the only way to get a random distribution of bits. + do + { + assert(state->rn_seed_fractional != 0); + state->rn_seed_fractional + = INTFUNC_rn_power_res_16807_mapping(state->rn_seed_fractional); + } while (state->rn_seed_fractional & 0xC0000000); + + //At this point the lower 30 bits should be random. + state->bit_buffer = state->rn_seed_fractional; + state->n_bb_valid = 30; + } + + +unsigned int ESRG_RAND_INT_Alg01_RandomBit( + struct ESRG_RAND_INT_Alg01RngState *state + ) + { + int rv; + + assert(state != NULL); + + //Restock the supply of bits if necessary. + if (state->n_bb_valid == 0) + ESRG_RAND_INT_Alg01_RestockBitBuffer(state); + + if (state->bit_buffer & 0x01) + rv = 1; + else + rv = 0; + + state->bit_buffer >>= 1; + state->n_bb_valid--; + + return(rv); + } + + +unsigned int ESRG_RAND_INT_Alg01_RandomByte( + struct ESRG_RAND_INT_Alg01RngState *state + ) + { + int rv; + + assert(state != NULL); + + //Be sure enough bits to yank a byte. + if (state->n_bb_valid < 8) + ESRG_RAND_INT_Alg01_RestockBitBuffer(state); + + //Grab the byte and return. + rv = state->bit_buffer & 0xFF; + state->bit_buffer >>= 8; //Must roll down to get new set of bits. + state->n_bb_valid -= 8; + + return(rv); + } + + +const char *ESRG_RAND_INT_cvcinfo(void) + { + return("$Header$"); + } + + +const char *ESRG_RAND_INT_hvcinfo(void) + { + return(ESRG_RAND_INT_H_VERSION); + } + +//End of esrg_rand_int.c.