home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 8
/
FreshFishVol8-CD2.bin
/
bbs
/
comm
/
amitcp-3.0ß2.lha
/
AmiTCP
/
src
/
devs
/
agnet
/
lrandom.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-08
|
7KB
|
240 lines
RCS_ID_C="$Id: lrandom.c,v 3.1 93/10/07 19:24:23 ppessi Exp $";
/*
* random.c --- generate random integers
*
* Author: ppessi <Pekka.Pessi@hut.fi>
*
* Copyright (c) 1993 OHT-AmiTCP/IP Group,
* Helsinki University of Technology, Finland.
* All rights reserved.
*
* Created : Wed Feb 24 08:24:13 1993 ppessi
* Last modified: Thu Oct 7 18:20:20 1993 ppessi
*
* $Log: lrandom.c,v $
* Revision 3.1 93/10/07 19:24:23 ppessi
* Release 2.1 version
*
* Revision 2.0 93/05/14 16:50:37 ppessi
* Release version.
*
*/
#include <exec/types.h>
#include <exec/io.h>
#include <devices/timer.h>
#include <clib/timer_protos.h>
#include <pragmas/timer_pragmas.h>
#ifndef TEST
#include "agnet.h"
#include "bases.h"
#else
extern struct Device *TimerBase ;
#endif
/****** random.module/LRandom ******************************************
*
* NAME
* LRandom -- Random number generator
*
* SYNOPSIS
* LRandom()
*
* LONG InitLRandom(VOID)
*
* FUNCTION
* Generates a random long integer. The random number generator
* must have been initialized before calling LRandom() or strange
* things will happen.
*
* LRandom() generates fairly good random numbers, all bits in the
* long word seem to be useful.
*
* BUGS
* None known.
*
* SEE ALSO
* InitLRandom, timer.device/GetSysTime()
*
******************************************************************************
*/
static union random_seed {
struct timeval time;
ULONG longs[2];
UWORD words[4];
} seed;
static const UWORD random_offset[4] = { 0x7823, 0xab34, 0x93b4, 0x7673 };
static const UWORD random_eor[4] = { 0xc97d, 0x6988, 0x32e9, 0x8487 };
ULONG LRandom(VOID)
{
ULONG carry = 0;
int i;
for (i = 3; i >= 0; i--) {
carry += seed.words[i]*34639L + random_offset[i];
seed.words[i] = carry ^ random_eor[i];
carry >>= 16;
}
return (ULONG)(seed.words[3] << 24) + (seed.words[2]<<16) +
(seed.words[1] << 8) + seed.words[0];
}
/****** random.module/InitLRandom ******************************************
*
* NAME
* InitLRandom -- initialize LRandom generator
*
* SYNOPSIS
* InitLRandom()
*
* VOID InitLRandom(VOID)
*
* FUNCTION
* Initializes the random number generator with the current time.
*
* NOTES
* This function uses GetSysTime() to get the initial seed for the
* random number generator. Thus it needs the V36 timer.device.
*
* BUGS
* None known.
*
* SEE ALSO
* LRandom, timer.device/GetSysTime()
*
******************************************************************************
*/
VOID InitLRandom(VOID)
{
GetSysTime(&seed.time);
(VOID) LRandom(); (VOID) LRandom(); (VOID) LRandom(); (VOID) LRandom();
(VOID) LRandom(); (VOID) LRandom(); (VOID) LRandom(); (VOID) LRandom();
}
/****** random.module/RandomDev ******************************************
*
* NAME
* RandomDev -- Binomial distribution generator
*
* SYNOPSIS
* RandomDev(mean, deviation)
*
* ULONG RandomDev(ULONG mean, ULONG deviation)
*
* FUNCTION
* RandomDev generates a random number in a binomial (n=16)
* distribution, which have specified mean and standard deviation.
* Whole distribution should be in the domain of the ULONG,
* otherwise the mean and/or the deviation of generated numbers
* may have unexpected values.
*
* BUGS
* There are only a 16 distinct values for the deviation.
*
* SEE ALSO
* InitLRandom, timer.device/GetSysTime()
*
******************************************************************************
*/
static const UWORD sdev[257] =
{ 65535, 63519, 61565, 59671, 57835, 56056, 54332, 52661,
51041, 49471, 47950, 46476, 45048, 43664, 42322, 41022,
39762, 38542, 37359, 36212, 35102, 34025, 32982, 31972,
30992, 30044, 29124, 28233, 27370, 26534, 25723, 24938,
24177, 23440, 22725, 22033, 21363, 20713, 20083, 19473,
18882, 18310, 17755, 17217, 16696, 16192, 15702, 15229,
14770, 14325, 13894, 13476, 13071, 12679, 12299, 11931,
11574, 11229, 10894, 10569, 10255, 9950, 9655, 9369,
9091, 8823, 8562, 8310, 8065, 7828, 7599, 7376,
7160, 6951, 6749, 6552, 6362, 6177, 5999, 5825,
5657, 5494, 5337, 5184, 5035, 4891, 4752, 4617,
4486, 4359, 4236, 4116, 4000, 3888, 3779, 3674,
3571, 3472, 3376, 3282, 3192, 3104, 3018, 2936,
2856, 2778, 2702, 2629, 2558, 2489, 2422, 2357,
2294, 2233, 2174, 2116, 2061, 2006, 1954, 1903,
1853, 1805, 1758, 1713, 1668, 1626, 1584, 1544,
1504, 1466, 1429, 1393, 1358, 1324, 1291, 1259,
1228, 1197, 1168, 1139, 1111, 1084, 1058, 1032,
1007, 983, 959, 936, 914, 892, 871, 850,
830, 811, 792, 773, 755, 738, 720, 704,
687, 671, 656, 641, 626, 612, 598, 584,
571, 558, 545, 533, 521, 509, 497, 486,
475, 464, 454, 443, 433, 423, 414, 404,
395, 386, 377, 368, 360, 352, 343, 335,
328, 320, 312, 305, 298, 291, 284, 277,
270, 263, 257, 250, 244, 238, 232, 226,
220, 214, 208, 203, 197, 192, 186, 181,
176, 170, 165, 160, 155, 150, 145, 141,
136, 131, 126, 122, 117, 113, 108, 104,
99, 95, 90, 86, 82, 78, 73, 69,
65, 61, 57, 53, 48, 44, 40, 36,
32, 28, 24, 20, 16, 12, 8, 4 };
const static BYTE ones[16] =
{ 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
ULONG RandomDev(ULONG mean, ULONG deviation)
{
WORD m, k, actual, done;
ULONG relative;
ULONG x = LRandom();
WORD offset;
/* Define the multiplier (actually mpr/256) */
relative = (deviation<<8)/mean;
/* find suitable multiplier */
m = 128; k=64;
while (k) {
if (sdev[m] > relative)
m += k;
else
m -= k;
k >>=1;
}
/*
* Count '1' bits in a lower word of x
*/
actual = ones[x >> 12 & 0xf] + ones[x >> 8 & 0xf]
+ ones[x >> 4 & 0xf] + ones[x & 0xf];
/*
* delay * (m/256)**(16-actual) * ((512-m)/256)**actual
*/
x = mean; offset = 0;
/* scale x */
while (x < 0x4000) {
x <<= 8; offset += 8;
}
while (x < 0x40000) {
x <<= 4; offset += 4;
}
while (x < 0x400000) {
x <<= 1; offset += 1;
}
done = actual > 16 - actual ? 16 - actual : actual;
for (k = done; k > 0; k--) {
x = (x * (512 - m) >> 8) * m >> 8;
}
for (k = done; k < 16 - done; k++) {
if (k < actual) {
x = x * (512 - m) >> 8;
/* multiplication may overflow without this scaling */
while (x >= 0x800000) { x >>= 1; offset--; }
}
else if (k >= actual) {
/* we do not miss the lost accuracy, do we? */
x = x * m >> 8;
}
}
return x >> offset;
}