1/*
2 * $Id: rng64.c,v 1.7 2008/03/21 17:38:39 jms Exp $
3 *
4 * This software contains proprietary and confidential information of Gradient
5 * Systems Inc. By accepting transfer of this copy, Recipient agrees
6 * to retain this software in confidence, to prevent disclosure to others, and
7 * to make no use of this software other than that for which it was delivered.
8 * This is an unpublished copyright work Gradient Systems, Inc. Execpt as
9 * permitted by federal law, 17 USC 117, copying is strictly prohibited.
10 *
11 * Gradient Systems Inc. CONFIDENTIAL - (Gradient Systems Inc. Confidential
12 * when combined with the aggregated modules for this product)
13 * OBJECT CODE ONLY SOURCE MATERIALS
14 * (C) COPYRIGHT Gradient Systems Inc. 2003
15 *
16 * All Rights Reserved
17 * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF GRADIENT SYSTEMS, INC.
18 * The copyright notice above does not evidence any
19 * actual or intended publication of such source code.
20 *
21 * Revision History
22 * ===================
23 * $Log: rng64.c,v $
24 * Revision 1.7 2008/03/21 17:38:39 jms
25 * changes for 2.6.3
26 *
27 * Revision 1.6 2006/04/26 23:20:05 jms
28 * Data type clenaup for qgen
29 *
30 * Revision 1.5 2006/03/08 21:25:27 jms
31 * change to RNG64 to address overflow/underflow issues
32 *
33 * Revision 1.4 2005/10/25 17:26:38 jms
34 * check in integration between microsoft changes and baseline code
35 *
36 * Revision 1.3 2005/03/04 19:48:39 jms
37 * Changes from Doug Johnson to address very large scale factors
38 *
39 * Revision 1.2 2005/01/03 20:08:59 jms
40 * change line terminations
41 *
42 * Revision 1.1.1.1 2004/11/24 23:31:47 jms
43 * re-establish external server
44 *
45 * Revision 1.2 2004/02/18 16:45:30 jms
46 * remove C++ style comments for AIX compiler
47 *
48 * Revision 1.1.1.1 2003/08/08 21:57:34 jms
49 * recreation after CVS crash
50 *
51 * Revision 1.1 2003/08/08 21:57:34 jms
52 * first integration of rng64 for o_custkey and l_partkey
53 *
54 */
55#include "rng64.h"
56
57#include <stdio.h>
58#include <stdlib.h>
59extern double dM;
60
61extern seed_t Seed[];
62
63void dss_random64(DSS_HUGE *tgt, DSS_HUGE nLow, DSS_HUGE nHigh, long nStream) {
64 DSS_HUGE nTemp;
65
66 if (nStream < 0 || nStream > MAX_STREAM)
67 nStream = 0;
68
69 if (nLow > nHigh) {
70 nTemp = nLow;
71 nLow = nHigh;
72 nHigh = nTemp;
73 }
74
75 Seed[nStream].value = NextRand64(Seed[nStream].value);
76 nTemp = Seed[nStream].value;
77 if (nTemp < 0)
78 nTemp = -nTemp;
79 nTemp %= (nHigh - nLow + 1);
80 *tgt = nLow + nTemp;
81 Seed[nStream].usage += 1;
82#ifdef RNG_TEST
83 Seed[nStream].nCalls += 1;
84#endif
85
86 return;
87}
88
89DSS_HUGE
90NextRand64(DSS_HUGE nSeed) {
91
92 DSS_HUGE a = (unsigned DSS_HUGE)RNG_A;
93 DSS_HUGE c = (unsigned DSS_HUGE)RNG_C;
94 nSeed = (nSeed * a + c); /* implicitely truncated to 64bits */
95
96 return (nSeed);
97}
98
99DSS_HUGE AdvanceRand64(DSS_HUGE nSeed, DSS_HUGE nCount) {
100 unsigned DSS_HUGE a = RNG_A;
101 unsigned DSS_HUGE c = RNG_C;
102 int nBit;
103 unsigned DSS_HUGE Apow = a, Dsum = c;
104
105 /* if nothing to do, do nothing ! */
106 if (nCount == 0)
107 return nSeed;
108
109 /* Recursively compute X(n) = A * X(n-1) + C */
110 /* */
111 /* explicitely: */
112 /* X(n) = A^n * X(0) + { A^(n-1) + A^(n-2) + ... A + 1 } * C */
113 /* */
114 /* we write this as: */
115 /* X(n) = Apow(n) * X(0) + Dsum(n) * C */
116 /* */
117 /* we use the following relations: */
118 /* Apow(n) = A^(n%2)*Apow(n/2)*Apow(n/2) */
119 /* Dsum(n) = (n%2)*Apow(n/2)*Apow(n/2) + (Apow(n/2) + 1) * Dsum(n/2) */
120 /* */
121
122 /* first get the highest non-zero bit */
123 for (nBit = 0; (nCount >> nBit) != RNG_C; nBit++) {
124 }
125
126 /* go 1 bit at the time */
127 while (--nBit >= 0) {
128 Dsum *= (Apow + 1);
129 Apow = Apow * Apow;
130 if (((nCount >> nBit) % 2) == 1) { /* odd value */
131 Dsum += Apow;
132 Apow *= a;
133 }
134 }
135 nSeed = nSeed * Apow + Dsum * c;
136 return nSeed;
137}
138