| 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 | |
| 74 | namespace 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. |
| 82 | typedef 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 | |
| 91 | class CRandom { |
| 92 | private: |
| 93 | RNGSEED m_seed; |
| 94 | inline RNGSEED UInt64Rand(void); |
| 95 | |
| 96 | public: |
| 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 | |