Imported Upstream version 0.72
This commit is contained in:
150
random.c
Normal file
150
random.c
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 1983 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is derived from the Berkeley source:
|
||||
* @(#)random.c 5.5 (Berkeley) 7/6/88
|
||||
* It was reworked for the GNU C Library by Roland McGrath.
|
||||
* Rewritten to use reentrant functions by Ulrich Drepper, 1995.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is derived from glibc-2.1:
|
||||
* glibc2.1/stdlib/random.c
|
||||
* glibc2.1/stdlib/random_r.c
|
||||
* Code was reworked and cut down to be a work-alike of the default
|
||||
* settings of srandom() and random() by Carsten Gn<47>rlich, 2004.
|
||||
*
|
||||
* Note that the original code is much more sophisticated than this one,
|
||||
* so you will probably want to review the real thing if you are
|
||||
* interested in the inner workings of the original glibc functions.
|
||||
*
|
||||
* There's nothing special about this code; it's simply here to
|
||||
* provide consistency among systems with different random()
|
||||
* implementations. E.g. it makes sure that dvdisaster produces
|
||||
* the same "random" images on all supported platforms.
|
||||
*
|
||||
* Note that unlike in the real thing, you must call SRandom()
|
||||
* before using Random() the first time.
|
||||
*/
|
||||
|
||||
#include "dvdisaster.h"
|
||||
|
||||
/* Some hardcoded values from glibc's default setting. */
|
||||
|
||||
#define MY_DEG 31
|
||||
#define MY_SEP 3
|
||||
|
||||
/*
|
||||
* State information for the random number generator.
|
||||
*/
|
||||
|
||||
static gint32 *fptr; /* Front pointer. */
|
||||
static gint32 *rptr; /* Rear pointer. */
|
||||
static gint32 state[MY_DEG]; /* Array of state values. */
|
||||
static gint32 *end_ptr; /* Pointer behind state table. */
|
||||
|
||||
/* Initialize the random number generator based on the given seed
|
||||
* via a linear congruential generator.
|
||||
* Then, the pointers are set to known locations that are exactly
|
||||
* MY_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.
|
||||
*/
|
||||
|
||||
void SRandom(gint32 seed)
|
||||
{ gint32 i;
|
||||
gint32 word;
|
||||
|
||||
/* We must make sure the seed is not 0.
|
||||
* Take arbitrarily 1 in this case. */
|
||||
|
||||
if (!seed) seed = 1;
|
||||
|
||||
/* This does: state[i] = (16807 * state[i - 1]) % 2147483647;
|
||||
but avoids overflowing 31 bits. */
|
||||
|
||||
state[0] = word = seed;
|
||||
for (i=1; i < MY_DEG; i++)
|
||||
{ gint32 hi = word / 127773;
|
||||
gint32 lo = word % 127773;
|
||||
|
||||
word = 16807 * lo - 2836 * hi;
|
||||
if (word < 0) word += 2147483647;
|
||||
|
||||
state[i] = word;
|
||||
}
|
||||
|
||||
/* Now prepare the pointers and cycle the state info 10 times around */
|
||||
|
||||
fptr = state + MY_SEP;
|
||||
rptr = state;
|
||||
end_ptr = state + MY_DEG;
|
||||
|
||||
for(i=10*MY_DEG; i; i--)
|
||||
Random();
|
||||
}
|
||||
|
||||
/* Deliver the next pseudo-random number in the current series.
|
||||
* This uses only the trinomial branch of the original code,
|
||||
* which is supposed to give the best results.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
gint32 Random(void)
|
||||
{ gint32 val,result;
|
||||
|
||||
val = *fptr += *rptr;
|
||||
|
||||
/* Chucking least random bit. */
|
||||
result = (val >> 1) & 0x7fffffff;
|
||||
|
||||
++fptr;
|
||||
if(fptr >= end_ptr)
|
||||
{ fptr = state;
|
||||
++rptr;
|
||||
}
|
||||
else
|
||||
{ ++rptr;
|
||||
if(rptr >= end_ptr)
|
||||
rptr = state;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Create a 32-bit random value from two sequential 31-bit values.
|
||||
* Note that this is all simple stuff to produce a sequence of "different"
|
||||
* numbers; it's not meant to deliver cryptographically strong random
|
||||
* sequences.
|
||||
*/
|
||||
|
||||
guint32 Random32(void)
|
||||
{ guint32 value;
|
||||
|
||||
value = (Random() & 0xffff);
|
||||
value <<= 16;
|
||||
value |= (Random() & 0xffff);
|
||||
|
||||
return value;
|
||||
}
|
||||
Reference in New Issue
Block a user