home *** CD-ROM | disk | FTP | other *** search
- 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;
- }
-
-
-