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
93char *env_config PROTO((char *tag, char *dflt));
94void NthElement(DSS_HUGE, DSS_HUGE *);
95
96void
97dss_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
105void
106row_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
115void
116row_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
146void
147dump_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 */
170DSS_HUGE
171NextRand(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 */
193DSS_HUGE
194UnifInt(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