1 | /* |
2 | * $Id: rnd.c,v 1.7 2006/07/31 17:23:09 jms Exp $ |
3 | * |
4 | * Revision History |
5 | * =================== |
6 | * $Log: rnd.c,v $ |
7 | * Revision 1.7 2006/07/31 17:23:09 jms |
8 | * fix to parallelism problem |
9 | * |
10 | * Revision 1.6 2005/10/25 17:26:38 jms |
11 | * check in integration between microsoft changes and baseline code |
12 | * |
13 | * Revision 1.5 2005/10/14 23:16:54 jms |
14 | * fix for answer set compliance |
15 | * |
16 | * Revision 1.4 2005/09/23 22:29:35 jms |
17 | * fix to assume 64b support in the 32b RNG calls. Should speed generation, and corrects a problem with FK between Customer and Orders |
18 | * |
19 | * Revision 1.3 2005/03/04 21:43:23 jms |
20 | * correct segfult in random() |
21 | * |
22 | * Revision 1.2 2005/01/03 20:08:59 jms |
23 | * change line terminations |
24 | * |
25 | * Revision 1.1.1.1 2004/11/24 23:31:47 jms |
26 | * re-establish external server |
27 | * |
28 | * Revision 1.7 2004/04/08 17:34:15 jms |
29 | * cleanup SOLARIS/SUN ifdefs; now all use SUN |
30 | * |
31 | * Revision 1.6 2004/03/26 20:22:56 jms |
32 | * correct Solaris header |
33 | * |
34 | * Revision 1.5 2004/03/02 20:50:50 jms |
35 | * MP/RAS porting changes |
36 | * |
37 | * Revision 1.4 2004/02/18 16:37:33 jms |
38 | * add int32_t for solaris |
39 | * |
40 | * Revision 1.3 2004/02/18 16:26:49 jms |
41 | * 32/64 bit changes for overflow handling needed additional changes when ported back to windows |
42 | * |
43 | * Revision 1.2 2004/02/18 16:17:32 jms |
44 | * add 32bit specific changes to UnifInt |
45 | * |
46 | * Revision 1.1.1.1 2003/08/08 21:50:34 jms |
47 | * recreation after CVS crash |
48 | * |
49 | * Revision 1.3 2003/08/08 21:35:26 jms |
50 | * first integration of rng64 for o_custkey and l_partkey |
51 | * |
52 | * Revision 1.2 2003/08/07 17:58:34 jms |
53 | * Convery RNG to 64bit space as preparation for new large scale RNG |
54 | * |
55 | * Revision 1.1.1.1 2003/04/03 18:54:21 jms |
56 | * initial checkin |
57 | * |
58 | * |
59 | */ |
60 | /* |
61 | * RANDOM.C -- Implements Park & Miller's "Minimum Standard" RNG |
62 | * |
63 | * (Reference: CACM, Oct 1988, pp 1192-1201) |
64 | * |
65 | * NextRand: Computes next random integer |
66 | * UnifInt: Yields an long uniformly distributed between given bounds |
67 | * UnifReal: ields a real uniformly distributed between given bounds |
68 | * Exponential: Yields a real exponentially distributed with given mean |
69 | * |
70 | */ |
71 | |
72 | #include "config.h" |
73 | #include <stdio.h> |
74 | #include <math.h> |
75 | #if (defined(LINUX)||defined(_POSIX_SOURCE)) |
76 | #include <stdint.h> |
77 | #endif |
78 | #ifdef IBM |
79 | #include <inttypes.h> |
80 | #endif |
81 | #ifdef SUN |
82 | #include <inttypes.h> |
83 | #endif |
84 | #ifdef ATT |
85 | #include <sys/bitypes.h> |
86 | #endif |
87 | #ifdef WIN32 |
88 | #define int32_t __int32 |
89 | #endif |
90 | #include "dss.h" |
91 | #include "rnd.h" |
92 | |
93 | char *env_config PROTO((char *tag, char *dflt)); |
94 | void NthElement(DSS_HUGE, DSS_HUGE *); |
95 | |
96 | void |
97 | dss_random(DSS_HUGE *tgt, DSS_HUGE lower, DSS_HUGE upper, long stream) |
98 | { |
99 | *tgt = UnifInt(lower, upper, stream); |
100 | Seed[stream].usage += 1; |
101 | |
102 | return; |
103 | } |
104 | |
105 | void |
106 | row_start(int t) \ |
107 | { |
108 | int i; |
109 | for (i=0; i <= MAX_STREAM; i++) |
110 | Seed[i].usage = 0 ; |
111 | |
112 | return; |
113 | } |
114 | |
115 | void |
116 | row_stop(int t) \ |
117 | { |
118 | int i; |
119 | |
120 | /* need to allow for handling the master and detail together */ |
121 | if (t == ORDER_LINE) |
122 | t = ORDER; |
123 | if (t == PART_PSUPP) |
124 | t = PART; |
125 | |
126 | for (i=0; i <= MAX_STREAM; i++) |
127 | if ((Seed[i].table == t) || (Seed[i].table == tdefs[t].child)) |
128 | { |
129 | if (set_seeds && (Seed[i].usage > Seed[i].boundary)) |
130 | { |
131 | fprintf(stderr, "\nSEED CHANGE: seed[%d].usage = %ld\n" , |
132 | i, Seed[i].usage); |
133 | Seed[i].boundary = Seed[i].usage; |
134 | } |
135 | else |
136 | { |
137 | NthElement((Seed[i].boundary - Seed[i].usage), &Seed[i].value); |
138 | #ifdef RNG_TEST |
139 | Seed[i].nCalls += Seed[i].boundary - Seed[i].usage; |
140 | #endif |
141 | } |
142 | } |
143 | return; |
144 | } |
145 | |
146 | void |
147 | dump_seeds(int tbl) |
148 | { |
149 | int i; |
150 | |
151 | for (i=0; i <= MAX_STREAM; i++) |
152 | if (Seed[i].table == tbl) |
153 | #ifdef RNG_TEST |
154 | printf("%d(%ld):\t%ld\n" , i, Seed[i].nCalls, Seed[i].value); |
155 | #else |
156 | printf("%d:\t%ld\n" , i, Seed[i].value); |
157 | #endif |
158 | return; |
159 | } |
160 | |
161 | /****************************************************************** |
162 | |
163 | NextRand: Computes next random integer |
164 | |
165 | *******************************************************************/ |
166 | |
167 | /* |
168 | * long NextRand( long nSeed ) |
169 | */ |
170 | DSS_HUGE |
171 | NextRand(DSS_HUGE nSeed) |
172 | |
173 | /* |
174 | * nSeed is the previous random number; the returned value is the |
175 | * next random number. The routine generates all numbers in the |
176 | * range 1 .. nM-1. |
177 | */ |
178 | |
179 | { |
180 | nSeed = (nSeed * 16807) % 2147483647; |
181 | return (nSeed); |
182 | } |
183 | |
184 | /****************************************************************** |
185 | |
186 | UnifInt: Yields an long uniformly distributed between given bounds |
187 | |
188 | *******************************************************************/ |
189 | |
190 | /* |
191 | * long UnifInt( long nLow, long nHigh, long nStream ) |
192 | */ |
193 | DSS_HUGE |
194 | UnifInt(DSS_HUGE nLow, DSS_HUGE nHigh, long nStream) |
195 | |
196 | /* |
197 | * Returns an integer uniformly distributed between nLow and nHigh, |
198 | * including * the endpoints. nStream is the random number stream. |
199 | * Stream 0 is used if nStream is not in the range 0..MAX_STREAM. |
200 | */ |
201 | |
202 | { |
203 | double dRange; |
204 | DSS_HUGE nTemp, |
205 | nRange; |
206 | int32_t nLow32 = (int32_t)nLow, |
207 | nHigh32 = (int32_t)nHigh; |
208 | |
209 | if (nStream < 0 || nStream > MAX_STREAM) |
210 | nStream = 0; |
211 | |
212 | if ((nHigh == MAX_LONG) && (nLow == 0)) |
213 | { |
214 | dRange = DOUBLE_CAST (nHigh32 - nLow32 + 1); |
215 | nRange = nHigh32 - nLow32 + 1; |
216 | } |
217 | else |
218 | { |
219 | dRange = DOUBLE_CAST (nHigh - nLow + 1); |
220 | nRange = nHigh - nLow + 1; |
221 | } |
222 | |
223 | Seed[nStream].value = NextRand(Seed[nStream].value); |
224 | #ifdef RNG_TEST |
225 | Seed[nStream].nCalls += 1; |
226 | #endif |
227 | nTemp = (DSS_HUGE) (((double) Seed[nStream].value / dM) * (dRange)); |
228 | return (nLow + nTemp); |
229 | } |
230 | |
231 | |
232 | |
233 | |