1/*
2 * Legal Notice
3 *
4 * This document and associated source code (the "Work") is a part of a
5 * benchmark specification maintained by the TPC.
6 *
7 * The TPC reserves all right, title, and interest to the Work as provided
8 * under U.S. and international laws, including without limitation all patent
9 * and trademark rights therein.
10 *
11 * No Warranty
12 *
13 * 1.1 TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE INFORMATION
14 * CONTAINED HEREIN IS PROVIDED "AS IS" AND WITH ALL FAULTS, AND THE
15 * AUTHORS AND DEVELOPERS OF THE WORK HEREBY DISCLAIM ALL OTHER
16 * WARRANTIES AND CONDITIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
17 * INCLUDING, BUT NOT LIMITED TO, ANY (IF ANY) IMPLIED WARRANTIES,
18 * DUTIES OR CONDITIONS OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
19 * PURPOSE, OF ACCURACY OR COMPLETENESS OF RESPONSES, OF RESULTS, OF
20 * WORKMANLIKE EFFORT, OF LACK OF VIRUSES, AND OF LACK OF NEGLIGENCE.
21 * ALSO, THERE IS NO WARRANTY OR CONDITION OF TITLE, QUIET ENJOYMENT,
22 * QUIET POSSESSION, CORRESPONDENCE TO DESCRIPTION OR NON-INFRINGEMENT
23 * WITH REGARD TO THE WORK.
24 * 1.2 IN NO EVENT WILL ANY AUTHOR OR DEVELOPER OF THE WORK BE LIABLE TO
25 * ANY OTHER PARTY FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO THE
26 * COST OF PROCURING SUBSTITUTE GOODS OR SERVICES, LOST PROFITS, LOSS
27 * OF USE, LOSS OF DATA, OR ANY INCIDENTAL, CONSEQUENTIAL, DIRECT,
28 * INDIRECT, OR SPECIAL DAMAGES WHETHER UNDER CONTRACT, TORT, WARRANTY,
29 * OR OTHERWISE, ARISING IN ANY WAY OUT OF THIS OR ANY OTHER AGREEMENT
30 * RELATING TO THE WORK, WHETHER OR NOT SUCH AUTHOR OR DEVELOPER HAD
31 * ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * Contributors
34 * - Sergey Vasilevskiy, Cecil Reames, Matt Emmerton
35 */
36
37#ifndef RANDOM_H
38#define RANDOM_H
39
40#include "EGenStandardTypes.h"
41
42/*
43 * Notes to Future EGen Coders:
44 *
45 * The Random routines have been rewritten to eliminate all uses of
46 * floating-point operations, so as to improve portability of EGen across
47 * platforms and compilers.
48 *
49 * All Random routines now generate a random range of integer values, even if
50 * those values are later converted back to floating-point for the caller.
51 *
52 * The same rules apply in the Random code as in the CMoney class:
53 * - It is OK to store and transport a value in a double.
54 * - It is not OK to perform calculations directly on a value in a double.
55 *
56 * Performing calculations directly on doubles can cause EGen subtle problems:
57 * - Rounding differences between 80-bit and 64-bit double operands.
58 * - Precision loss for large integers stored into 64-bit doubles.
59 * - Integer range operations that rarely return an output one too large.
60 * - Differences between initial database population and runtime inputs
61 * when executed on two different platforms / compilers.
62 *
63 * The RndDouble() and RndDoubleRange() routines are now deprecated. The
64 * RndDoubleIncrRange() routine is the replacement for these deprecated
65 * routines. This routine takes a pair of range parameters, plus an increment
66 * argument. It produces a range of integer values, which are converted to a
67 * discrete (not continuous) range of double values.
68 *
69 * All integer range routines now perform 96-bit or 128-bit integer
70 * multiplication with integer truncation of the lower 64 bits, thus avoiding
71 * use of RndDouble().
72 */
73
74namespace TPCE {
75
76// Constants
77#define UInt64Rand_A_MULTIPLIER UINT64_CONST(6364136223846793005)
78#define UInt64Rand_C_INCREMENT UINT64_CONST(1)
79#define UInt64Rand_ONE UINT64_CONST(1)
80
81// Independent RNG seed type.
82typedef UINT64 RNGSEED;
83
84#ifdef EGEN_USE_DEPRECATED_CODE
85
86// For efficiency, use a constant for 1/2^64.
87#define UInt64Rand_RECIPROCAL_2_POWER_64 (5.421010862427522e-20)
88
89#endif // EGEN_USE_DEPRECATED_CODE
90
91class CRandom {
92private:
93 RNGSEED m_seed;
94 inline RNGSEED UInt64Rand(void);
95
96public:
97 CRandom(void);
98 CRandom(RNGSEED seed);
99 ~CRandom(void){};
100
101 void SetSeed(RNGSEED seed);
102 inline RNGSEED GetSeed(void) {
103 return m_seed;
104 };
105 RNGSEED RndNthElement(RNGSEED nSeed, RNGSEED nCount);
106
107 // returns a random integer value in the range [min .. max]
108 int RndIntRange(int min, int max);
109
110 // returns a random 64-bit integer value in the range [min .. max]
111 INT64 RndInt64Range(INT64 min, INT64 max);
112
113 // returns a random integer value in the range [low .. high] excluding the
114 // value (exclude)
115 INT64 RndInt64RangeExclude(INT64 low, INT64 high, INT64 exclude);
116
117 // return Nth element in the sequence over the integer range
118 int RndNthIntRange(RNGSEED Seed, RNGSEED N, int min, int max);
119
120 // return Nth element in the sequence over the integer range
121 INT64 RndNthInt64Range(RNGSEED Seed, RNGSEED N, INT64 min, INT64 max);
122
123 // returns a random integer value in the range [low .. high] excluding the
124 // value (exclude)
125 int RndIntRangeExclude(int low, int high, int exclude);
126
127#ifdef EGEN_USE_DEPRECATED_CODE
128
129 // returns a random value in the range [0 ..
130 // 0.99999999999999999994578989137572] care should be taken in casting the
131 // result as a float because of the potential loss of precision.
132 double RndDouble(void);
133
134 // return Nth element in the sequence converted to double
135 double RndNthDouble(RNGSEED Seed, RNGSEED N);
136
137#endif // EGEN_USE_DEPRECATED_CODE
138
139 // returns a random double value in the range of [min .. max]
140 double RndDoubleRange(double min, double max);
141
142 // returns a random double value in the range of [min .. max] with incr
143 // precision
144 double RndDoubleIncrRange(double min, double max, double incr);
145
146 // returns a random double value from a negative exponential distribution
147 // with the given mean
148 double RndDoubleNegExp(double mean);
149
150 // returns TRUE or FALSE, with the chance of TRUE being as specified by
151 // (percent)
152 inline bool RndPercent(int percent) {
153 return (RndIntRange(1, 100) <= percent);
154 };
155
156 // Returns a random integer percentage (i.e. whole number between 1 and 100,
157 // inclusive)
158 inline UINT RndGenerateIntegerPercentage() {
159 return ((UINT)RndIntRange(1, 100));
160 }
161
162 /* Returns a non-uniform random 64-bit integer in range of [P .. Q].
163 *
164 * NURnd is used to create a skewed data access pattern. The function is
165 * similar to NURand in TPC-C. (The two functions are identical when C=0
166 * and s=0.)
167 *
168 * The parameter A must be of the form 2^k - 1, so that Rnd[0..A] will
169 * produce a k-bit field with all bits having 50/50 probability of being 0
170 * or 1.
171 *
172 * With a k-bit A value, the weights range from 3^k down to 1 with the
173 * number of equal probability values given by C(k,i) = k! /(i!(k-i)!) for
174 * 0 <= i <= k. So a bigger A value from a larger k has much more skew.
175 *
176 * Left shifting of Rnd[0..A] by "s" bits gets a larger interval without
177 * getting huge amounts of skew. For example, when applied to elapsed time
178 * in milliseconds, s=10 effectively ignores the milliseconds, while s=16
179 * effectively ignores seconds and milliseconds, giving a granularity of
180 * just over 1 minute (65.536 seconds). A smaller A value can then give
181 * the desired amount of skew at effectively one-minute resolution.
182 */
183 INT64 NURnd(INT64 P, INT64 Q, INT32 A, INT32 s);
184
185 // Returns random alphanumeric string obeying a specific format.
186 // For the format: n - given character must be numeric
187 // a - given character must be alphabetical
188 // Example: "nnnaannnnaannn"
189 void RndAlphaNumFormatted(char *szReturnString, const char *szFormat);
190};
191
192} // namespace TPCE
193
194#endif // RANDOM_H
195