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 "config.h" |
56 | #include "dss.h" |
57 | #include <stdio.h> |
58 | #include <stdlib.h> |
59 | #include "rng64.h" |
60 | extern double dM; |
61 | |
62 | extern seed_t Seed[]; |
63 | |
64 | void |
65 | dss_random64(DSS_HUGE *tgt, DSS_HUGE nLow, DSS_HUGE nHigh, long nStream) |
66 | { |
67 | DSS_HUGE nTemp; |
68 | |
69 | if (nStream < 0 || nStream > MAX_STREAM) |
70 | nStream = 0; |
71 | |
72 | if (nLow > nHigh) |
73 | { |
74 | nTemp = nLow; |
75 | nLow = nHigh; |
76 | nHigh = nTemp; |
77 | } |
78 | |
79 | Seed[nStream].value = NextRand64(Seed[nStream].value); |
80 | nTemp = Seed[nStream].value; |
81 | if (nTemp < 0) |
82 | nTemp = -nTemp; |
83 | nTemp %= (nHigh - nLow + 1); |
84 | *tgt = nLow + nTemp; |
85 | Seed[nStream].usage += 1; |
86 | #ifdef RNG_TEST |
87 | Seed[nStream].nCalls += 1; |
88 | #endif |
89 | |
90 | return; |
91 | } |
92 | |
93 | DSS_HUGE |
94 | NextRand64(DSS_HUGE nSeed){ |
95 | |
96 | DSS_HUGE a = (unsigned DSS_HUGE) RNG_A; |
97 | DSS_HUGE c = (unsigned DSS_HUGE) RNG_C; |
98 | nSeed = (nSeed * a + c); /* implicitely truncated to 64bits */ |
99 | |
100 | return (nSeed); |
101 | } |
102 | |
103 | DSS_HUGE AdvanceRand64( DSS_HUGE nSeed, |
104 | DSS_HUGE nCount) { |
105 | unsigned DSS_HUGE a = RNG_A ; |
106 | unsigned DSS_HUGE c = RNG_C ; |
107 | int nBit; |
108 | unsigned DSS_HUGE Apow=a, Dsum=c; |
109 | |
110 | /* if nothing to do, do nothing ! */ |
111 | if( nCount == 0 ) return nSeed; |
112 | |
113 | /* Recursively compute X(n) = A * X(n-1) + C */ |
114 | /* */ |
115 | /* explicitely: */ |
116 | /* X(n) = A^n * X(0) + { A^(n-1) + A^(n-2) + ... A + 1 } * C */ |
117 | /* */ |
118 | /* we write this as: */ |
119 | /* X(n) = Apow(n) * X(0) + Dsum(n) * C */ |
120 | /* */ |
121 | /* we use the following relations: */ |
122 | /* Apow(n) = A^(n%2)*Apow(n/2)*Apow(n/2) */ |
123 | /* Dsum(n) = (n%2)*Apow(n/2)*Apow(n/2) + (Apow(n/2) + 1) * Dsum(n/2) */ |
124 | /* */ |
125 | |
126 | /* first get the highest non-zero bit */ |
127 | for( nBit = 0; (nCount >> nBit) != RNG_C ; nBit ++){} |
128 | |
129 | /* go 1 bit at the time */ |
130 | while( --nBit >= 0 ) { |
131 | Dsum *= (Apow + 1); |
132 | Apow = Apow * Apow; |
133 | if( ((nCount >> nBit) % 2) == 1 ) { /* odd value */ |
134 | Dsum += Apow; |
135 | Apow *= a; |
136 | } |
137 | } |
138 | nSeed = nSeed * Apow + Dsum * c; |
139 | return nSeed; |
140 | } |
141 | |