1 /* 2 * ***************************************************************************** 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2018-2019 Gavin D. Howard and contributors. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * * Redistributions of source code must retain the above copyright notice, this 12 * list of conditions and the following disclaimer. 13 * 14 * * Redistributions in binary form must reproduce the above copyright notice, 15 * this list of conditions and the following disclaimer in the documentation 16 * and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 * ***************************************************************************** 31 * 32 * Parts of this code are adapted from the following: 33 * 34 * PCG, A Family of Better Random Number Generators. 35 * 36 * You can find the original source code at: 37 * https://github.com/imneme/pcg-c 38 * 39 * ----------------------------------------------------------------------------- 40 * 41 * Parts of this code are also under the following license: 42 * 43 * Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors 44 * 45 * Permission is hereby granted, free of charge, to any person obtaining a copy 46 * of this software and associated documentation files (the "Software"), to deal 47 * in the Software without restriction, including without limitation the rights 48 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 * copies of the Software, and to permit persons to whom the Software is 50 * furnished to do so, subject to the following conditions: 51 * 52 * The above copyright notice and this permission notice shall be included in 53 * all copies or substantial portions of the Software. 54 * 55 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 61 * SOFTWARE. 62 * 63 * ***************************************************************************** 64 * 65 * Definitions for the RNG. 66 * 67 */ 68 69 #ifndef BC_RAND_H 70 #define BC_RAND_H 71 72 #include <stdint.h> 73 #include <inttypes.h> 74 75 #include <vector.h> 76 #include <num.h> 77 78 #if BC_ENABLE_EXTRA_MATH 79 80 #if BC_ENABLE_RAND 81 82 typedef ulong (*BcRandUlong)(void*); 83 84 #if BC_LONG_BIT >= 64 85 86 #ifdef BC_RAND_BUILTIN 87 #if BC_RAND_BUILTIN 88 #ifndef __SIZEOF_INT128__ 89 #undef BC_RAND_BUILTIN 90 #define BC_RAND_BUILTIN (0) 91 #endif // __SIZEOF_INT128__ 92 #endif // BC_RAND_BUILTIN 93 #endif // BC_RAND_BUILTIN 94 95 #ifndef BC_RAND_BUILTIN 96 #ifdef __SIZEOF_INT128__ 97 #define BC_RAND_BUILTIN (1) 98 #else // __SIZEOF_INT128__ 99 #define BC_RAND_BUILTIN (0) 100 #endif // __SIZEOF_INT128__ 101 #endif // BC_RAND_BUILTIN 102 103 typedef uint64_t BcRand; 104 105 #define BC_RAND_ROTC (63) 106 107 #if BC_RAND_BUILTIN 108 109 typedef __uint128_t BcRandState; 110 111 #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 112 #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 113 114 #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 115 #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 116 117 #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 118 #define BC_RAND_ZERO(r) (!(r)->state) 119 120 #define BC_RAND_CONSTANT(h, l) ((((BcRandState) (h)) << 64) + (BcRandState) (l)) 121 122 #define BC_RAND_TRUNC(s) ((uint64_t) (s)) 123 #define BC_RAND_CHOP(s) ((uint64_t) ((s) >> 64UL)) 124 #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 122UL)) 125 126 #else // BC_RAND_BUILTIN 127 128 typedef struct BcRandState { 129 130 uint_fast64_t lo; 131 uint_fast64_t hi; 132 133 } BcRandState; 134 135 #define bc_rand_mul(a, b) (bc_rand_multiply((a), (b))) 136 #define bc_rand_add(a, b) (bc_rand_addition((a), (b))) 137 138 #define bc_rand_mul2(a, b) (bc_rand_multiply2((a), (b))) 139 #define bc_rand_add2(a, b) (bc_rand_addition2((a), (b))) 140 141 #define BC_RAND_NOTMODIFIED(r) (((r)->inc.lo & 1) == 0) 142 #define BC_RAND_ZERO(r) (!(r)->state.lo && !(r)->state.hi) 143 144 #define BC_RAND_CONSTANT(h, l) { .lo = (l), .hi = (h) } 145 146 #define BC_RAND_TRUNC(s) ((s).lo) 147 #define BC_RAND_CHOP(s) ((s).hi) 148 #define BC_RAND_ROTAMT(s) ((unsigned int) ((s).hi >> 58UL)) 149 150 #define BC_RAND_BOTTOM32 (((uint_fast64_t) 0xffffffffULL)) 151 #define BC_RAND_TRUNC32(n) ((n) & BC_RAND_BOTTOM32) 152 #define BC_RAND_CHOP32(n) ((n) >> 32) 153 154 #endif // BC_RAND_BUILTIN 155 156 #define BC_RAND_MULTIPLIER \ 157 BC_RAND_CONSTANT(2549297995355413924ULL, 4865540595714422341ULL) 158 159 #define BC_RAND_FOLD(s) ((BcRand) (BC_RAND_CHOP(s) ^ BC_RAND_TRUNC(s))) 160 161 #else // BC_LONG_BIT >= 64 162 163 #undef BC_RAND_BUILTIN 164 #define BC_RAND_BUILTIN (1) 165 166 typedef uint32_t BcRand; 167 168 #define BC_RAND_ROTC (31) 169 170 typedef uint_fast64_t BcRandState; 171 172 #define bc_rand_mul(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 173 #define bc_rand_add(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 174 175 #define bc_rand_mul2(a, b) (((BcRandState) (a)) * ((BcRandState) (b))) 176 #define bc_rand_add2(a, b) (((BcRandState) (a)) + ((BcRandState) (b))) 177 178 #define BC_RAND_NOTMODIFIED(r) (((r)->inc & 1UL) == 0) 179 #define BC_RAND_ZERO(r) (!(r)->state) 180 181 #define BC_RAND_CONSTANT UINT64_C 182 #define BC_RAND_MULTIPLIER BC_RAND_CONSTANT(6364136223846793005) 183 184 #define BC_RAND_TRUNC(s) ((uint32_t) (s)) 185 #define BC_RAND_CHOP(s) ((uint32_t) ((s) >> 32UL)) 186 #define BC_RAND_ROTAMT(s) ((unsigned int) ((s) >> 59UL)) 187 188 #define BC_RAND_FOLD(s) ((BcRand) ((((s) >> 18U) ^ (s)) >> 27U)) 189 190 #endif // BC_LONG_BIT >= 64 191 192 #define BC_RAND_ROT(v, r) \ 193 ((BcRand) (((v) >> (r)) | ((v) << ((0 - (r)) & BC_RAND_ROTC)))) 194 195 #define BC_RAND_BITS (sizeof(BcRand) * CHAR_BIT) 196 #define BC_RAND_STATE_BITS (sizeof(BcRandState) * CHAR_BIT) 197 198 #define BC_RAND_NUM_SIZE (BC_NUM_BIGDIG_LOG10 * 2 + 2) 199 200 #define BC_RAND_SRAND_BITS ((1 << CHAR_BIT) - 1) 201 202 typedef struct BcRNGData { 203 204 BcRandState state; 205 BcRandState inc; 206 207 } BcRNGData; 208 209 typedef struct BcRNG { 210 211 BcVec v; 212 213 } BcRNG; 214 215 void bc_rand_init(BcRNG *r); 216 #ifndef NDEBUG 217 void bc_rand_free(BcRNG *r); 218 #endif // NDEBUG 219 220 BcRand bc_rand_int(BcRNG *r); 221 BcRand bc_rand_bounded(BcRNG *r, BcRand bound); 222 void bc_rand_seed(BcRNG *r, ulong state1, ulong state2, ulong inc1, ulong inc2); 223 void bc_rand_push(BcRNG *r); 224 void bc_rand_pop(BcRNG *r, bool reset); 225 void bc_rand_getRands(BcRNG *r, BcRand *s1, BcRand *s2, BcRand *i1, BcRand *i2); 226 227 extern const BcRandState bc_rand_multiplier; 228 229 #endif // BC_ENABLE_RAND 230 231 #endif // BC_ENABLE_EXTRA_MATH 232 233 #endif // BC_RAND_H 234