| 1 | /* | 
|---|
| 2 | * RANDOM.C -- Implements Park & Miller's "Minimum Standard" RNG | 
|---|
| 3 | * | 
|---|
| 4 | * (Reference:  CACM, Oct 1988, pp 1192-1201) | 
|---|
| 5 | * | 
|---|
| 6 | * NextRand:  Computes next random integer | 
|---|
| 7 | * UnifInt:   Yields an long uniformly distributed between given bounds | 
|---|
| 8 | * UnifReal: ields a real uniformly distributed between given bounds | 
|---|
| 9 | * Exponential: Yields a real exponentially distributed with given mean | 
|---|
| 10 | * | 
|---|
| 11 | */ | 
|---|
| 12 |  | 
|---|
| 13 | #include "config.h" | 
|---|
| 14 |  | 
|---|
| 15 | #include <math.h> | 
|---|
| 16 | #include <stdio.h> | 
|---|
| 17 | #include <stdint.h> | 
|---|
| 18 | #include "dss.h" | 
|---|
| 19 | #include "rnd.h" | 
|---|
| 20 |  | 
|---|
| 21 | const char *env_config PROTO((const char *tag, const char *dflt)); | 
|---|
| 22 | void NthElement(DSS_HUGE, DSS_HUGE *); | 
|---|
| 23 |  | 
|---|
| 24 | void dss_random(DSS_HUGE *tgt, DSS_HUGE lower, DSS_HUGE upper, long stream) { | 
|---|
| 25 | *tgt = UnifInt(lower, upper, stream); | 
|---|
| 26 | Seed[stream].usage += 1; | 
|---|
| 27 |  | 
|---|
| 28 | return; | 
|---|
| 29 | } | 
|---|
| 30 |  | 
|---|
| 31 | void row_start(int t) { | 
|---|
| 32 | (void)t; | 
|---|
| 33 | int i; | 
|---|
| 34 | for (i = 0; i <= MAX_STREAM; i++) | 
|---|
| 35 | Seed[i].usage = 0; | 
|---|
| 36 |  | 
|---|
| 37 | return; | 
|---|
| 38 | } | 
|---|
| 39 |  | 
|---|
| 40 | void row_stop_h(int t) { | 
|---|
| 41 | int i; | 
|---|
| 42 |  | 
|---|
| 43 | /* need to allow for handling the master and detail together */ | 
|---|
| 44 | if (t == ORDER_LINE) | 
|---|
| 45 | t = ORDER; | 
|---|
| 46 | if (t == PART_PSUPP) | 
|---|
| 47 | t = PART; | 
|---|
| 48 |  | 
|---|
| 49 | for (i = 0; i <= MAX_STREAM; i++) | 
|---|
| 50 | if ((Seed[i].table == t) || (Seed[i].table == tdefs[t].child)) { | 
|---|
| 51 | if (set_seeds && (Seed[i].usage > Seed[i].boundary)) { | 
|---|
| 52 | fprintf(stderr, "\nSEED CHANGE: seed[%d].usage = "HUGE_FORMAT "\n", i, Seed[i].usage); | 
|---|
| 53 | Seed[i].boundary = Seed[i].usage; | 
|---|
| 54 | } else { | 
|---|
| 55 | NthElement((Seed[i].boundary - Seed[i].usage), &Seed[i].value); | 
|---|
| 56 | #ifdef RNG_TEST | 
|---|
| 57 | Seed[i].nCalls += Seed[i].boundary - Seed[i].usage; | 
|---|
| 58 | #endif | 
|---|
| 59 | } | 
|---|
| 60 | } | 
|---|
| 61 | return; | 
|---|
| 62 | } | 
|---|
| 63 |  | 
|---|
| 64 | void dump_seeds(int tbl) { | 
|---|
| 65 | int i; | 
|---|
| 66 |  | 
|---|
| 67 | for (i = 0; i <= MAX_STREAM; i++) | 
|---|
| 68 | if (Seed[i].table == tbl) | 
|---|
| 69 | #ifdef RNG_TEST | 
|---|
| 70 | printf( "%d("HUGE_FORMAT "):\t"HUGE_FORMAT "\n", i, Seed[i].nCalls, Seed[i].value); | 
|---|
| 71 | #else | 
|---|
| 72 | printf( "%d:\t"HUGE_FORMAT "\n", i, Seed[i].value); | 
|---|
| 73 | #endif | 
|---|
| 74 | return; | 
|---|
| 75 | } | 
|---|
| 76 |  | 
|---|
| 77 | /****************************************************************** | 
|---|
| 78 |  | 
|---|
| 79 | NextRand:  Computes next random integer | 
|---|
| 80 |  | 
|---|
| 81 | *******************************************************************/ | 
|---|
| 82 |  | 
|---|
| 83 | /* | 
|---|
| 84 | * long NextRand( long nSeed ) | 
|---|
| 85 | */ | 
|---|
| 86 | DSS_HUGE | 
|---|
| 87 | NextRand(DSS_HUGE nSeed) | 
|---|
| 88 |  | 
|---|
| 89 | /* | 
|---|
| 90 | * nSeed is the previous random number; the returned value is the | 
|---|
| 91 | * next random number. The routine generates all numbers in the | 
|---|
| 92 | * range 1 .. nM-1. | 
|---|
| 93 | */ | 
|---|
| 94 |  | 
|---|
| 95 | { | 
|---|
| 96 | nSeed = (nSeed * 16807) % 2147483647; | 
|---|
| 97 | return (nSeed); | 
|---|
| 98 | } | 
|---|
| 99 |  | 
|---|
| 100 | /****************************************************************** | 
|---|
| 101 |  | 
|---|
| 102 | UnifInt:  Yields an long uniformly distributed between given bounds | 
|---|
| 103 |  | 
|---|
| 104 | *******************************************************************/ | 
|---|
| 105 |  | 
|---|
| 106 | /* | 
|---|
| 107 | * long UnifInt( long nLow, long nHigh, long nStream ) | 
|---|
| 108 | */ | 
|---|
| 109 | DSS_HUGE | 
|---|
| 110 | UnifInt(DSS_HUGE nLow, DSS_HUGE nHigh, long nStream) | 
|---|
| 111 |  | 
|---|
| 112 | /* | 
|---|
| 113 | * Returns an integer uniformly distributed between nLow and nHigh, | 
|---|
| 114 | * including * the endpoints.  nStream is the random number stream. | 
|---|
| 115 | * Stream 0 is used if nStream is not in the range 0..MAX_STREAM. | 
|---|
| 116 | */ | 
|---|
| 117 |  | 
|---|
| 118 | { | 
|---|
| 119 | double dRange; | 
|---|
| 120 | DSS_HUGE nTemp; | 
|---|
| 121 | int32_t nLow32 = (int32_t)nLow, nHigh32 = (int32_t)nHigh; | 
|---|
| 122 |  | 
|---|
| 123 | if (nStream < 0 || nStream > MAX_STREAM) { | 
|---|
| 124 | nStream = 0; | 
|---|
| 125 | } | 
|---|
| 126 |  | 
|---|
| 127 | if ((nHigh == MAX_LONG) && (nLow == 0)) { | 
|---|
| 128 | dRange = (double)((DSS_HUGE)(nHigh32 - nLow32) + 1); | 
|---|
| 129 | } else { | 
|---|
| 130 | dRange = (double)(nHigh - nLow + 1); | 
|---|
| 131 | } | 
|---|
| 132 |  | 
|---|
| 133 | Seed[nStream].value = NextRand(Seed[nStream].value); | 
|---|
| 134 | #ifdef RNG_TEST | 
|---|
| 135 | Seed[nStream].nCalls += 1; | 
|---|
| 136 | #endif | 
|---|
| 137 | nTemp = (DSS_HUGE)(((double)Seed[nStream].value / dM) * (dRange)); | 
|---|
| 138 | return (nLow + nTemp); | 
|---|
| 139 | } | 
|---|
| 140 |  | 
|---|