📄 random.c
字号:
* that are exactly rand_sep places apart. Lastly, it cycles the state
* information a given number of times to get rid of any initial dependencies
* introduced by the L.C.R.N.G.
* Note that the initialization of randtbl[] for default usage relies on
* values produced by this routine.
*/
void
srandom( x )
unsigned x;
{
register int i;
if( rand_type == TYPE_0 ) {
state[ 0 ] = (long) x;
}
else {
state[ 0 ] = (long) x;
for( i = 1; i < rand_deg; i++ ) {
state[i] = 1103515245*state[i - 1] + 12345;
}
fptr = &state[ rand_sep ];
rptr = &state[ 0 ];
for( i = 0; i < 10*rand_deg; i++ ) random();
}
}
/*
* initstate:
* Initialize the state information in the given array of n bytes for
* future random number generation. Based on the number of bytes we
* are given, and the break values for the different R.N.G.'s, we choose
* the best (largest) one we can and set things up for it. srandom() is
* then called to initialize the state information.
* Note that on return from srandom(), we set state[-1] to be the type
* multiplexed with the current value of the rear pointer; this is so
* successive calls to initstate() won't lose this information and will
* be able to restart with setstate().
* Note: the first thing we do is save the current state, if any, just like
* setstate() so that it doesn't matter when initstate is called.
* Returns a pointer to the old state.
*/
char *
initstate( seed, arg_state, n )
unsigned seed; /* seed for R. N. G. */
char *arg_state; /* pointer to state array */
size_t n; /* # bytes of state info */
{
register char *ostate = (char *)( &state[ -1 ] );
if( rand_type == TYPE_0 ) state[ -1 ] = rand_type;
else state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
if( n < BREAK_1 ) {
if( n < BREAK_0 ) {
fprintf( stderr, "initstate: not enough state (%d bytes) with which to do jack; ignored.\n", n );
return 0;
}
rand_type = TYPE_0;
rand_deg = DEG_0;
rand_sep = SEP_0;
}
else {
if( n < BREAK_2 ) {
rand_type = TYPE_1;
rand_deg = DEG_1;
rand_sep = SEP_1;
}
else {
if( n < BREAK_3 ) {
rand_type = TYPE_2;
rand_deg = DEG_2;
rand_sep = SEP_2;
}
else {
if( n < BREAK_4 ) {
rand_type = TYPE_3;
rand_deg = DEG_3;
rand_sep = SEP_3;
}
else {
rand_type = TYPE_4;
rand_deg = DEG_4;
rand_sep = SEP_4;
}
}
}
}
state = &( ( (long *)arg_state )[1] ); /* first location */
end_ptr = &state[ rand_deg ]; /* must set end_ptr before srandom */
srandom( seed );
if( rand_type == TYPE_0 ) state[ -1 ] = rand_type;
else state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
return( ostate );
}
/*
* setstate:
* Restore the state from the given state array.
* Note: it is important that we also remember the locations of the pointers
* in the current state information, and restore the locations of the pointers
* from the old state information. This is done by multiplexing the pointer
* location into the zeroeth word of the state information.
* Note that due to the order in which things are done, it is OK to call
* setstate() with the same state as the current state.
* Returns a pointer to the old state information.
*/
char *
setstate( arg_state )
const char *arg_state;
{
register long *new_state = (long *)arg_state;
register int type = (int)new_state[0]%MAX_TYPES;
register int rear = (int)new_state[0]/MAX_TYPES;
char *ostate = (char *)( &state[ -1 ] );
if( rand_type == TYPE_0 ) state[ -1 ] = rand_type;
else state[ -1 ] = MAX_TYPES*(rptr - state) + rand_type;
switch( type ) {
case TYPE_0:
case TYPE_1:
case TYPE_2:
case TYPE_3:
case TYPE_4:
rand_type = type;
rand_deg = degrees[ type ];
rand_sep = seps[ type ];
break;
default:
fprintf( stderr, "setstate: state info has been munged; not changed.\n" );
}
state = &new_state[ 1 ];
if( rand_type != TYPE_0 ) {
rptr = &state[ rear ];
fptr = &state[ (rear + rand_sep)%rand_deg ];
}
end_ptr = &state[ rand_deg ]; /* set end_ptr too */
return( ostate );
}
/*
* random:
* If we are using the trivial TYPE_0 R.N.G., just do the old linear
* congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
* same in all ther other cases due to all the global variables that have been
* set up. The basic operation is to add the number at the rear pointer into
* the one at the front pointer. Then both pointers are advanced to the next
* location cyclically in the table. The value returned is the sum generated,
* reduced to 31 bits by throwing away the "least random" low bit.
* Note: the code takes advantage of the fact that both the front and
* rear pointers can't wrap on the same call by not testing the rear
* pointer if the front one has wrapped.
* Returns a 31-bit random number.
*/
long
random(void)
{
long i;
if( rand_type == TYPE_0 ) {
i = state[0] = ( state[0]*1103515245 + 12345 )&0x7fffffff;
}
else {
*fptr += *rptr;
i = (*fptr >> 1)&0x7fffffff; /* chucking least random bit */
if( ++fptr >= end_ptr ) {
fptr = state;
++rptr;
}
else {
if( ++rptr >= end_ptr ) rptr = state;
}
}
return( i );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -