Changes in libcfa/src/bits/random.hfa [3ff64cb:e57de69]
- File:
-
- 1 edited
-
libcfa/src/bits/random.hfa (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/bits/random.hfa
r3ff64cb re57de69 10 10 // Created On : Fri Jan 14 07:18:11 2022 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Dec 11 18:43:58 202213 // Update Count : 1 7112 // Last Modified On : Fri Jan 14 07:18:58 2022 13 // Update Count : 1 14 14 // 15 15 … … 18 18 #include <stdint.h> 19 19 20 #define GLUE2( x, y ) x##y 21 #define GLUE( x, y ) GLUE2( x, y ) 20 // Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is returned 21 // (copied), and then compute and store the next random value. 22 22 23 // Set default PRNG for architecture size. 24 #ifdef __x86_64__ // 64-bit architecture 25 // 64-bit generators 26 #define LEHMER64 27 //#define XORSHIFT_12_25_27 28 //#define XOSHIRO256PP 29 //#define KISS_64 30 31 // 32-bit generators 32 #define XORSHIFT_6_21_7 33 //#define XOSHIRO128PP 34 #else // 32-bit architecture 35 // 64-bit generators 36 #define XORSHIFT_13_7_17 37 38 // 32-bit generators 39 #define XORSHIFT_6_21_7 40 #endif // __x86_64__ 41 42 // Define C/CFA PRNG name and random-state. 43 44 // SKULLDUGGERY: typedefs name struct and typedef with the same name to deal with CFA typedef numbering problem. 45 46 #ifdef XOSHIRO256PP 47 #define PRNG_NAME_64 xoshiro256pp 48 #define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t) 49 typedef struct PRNG_STATE_64_T { uint64_t s[4]; } PRNG_STATE_64_T; 50 #endif // XOSHIRO256PP 51 52 #ifdef XOSHIRO128PP 53 #define PRNG_NAME_32 xoshiro128pp 54 #define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t) 55 typedef struct PRNG_STATE_32_T { uint32_t s[4]; } PRNG_STATE_32_T; 56 #endif // XOSHIRO128PP 57 58 #ifdef LEHMER64 59 #define PRNG_NAME_64 lehmer64 60 #define PRNG_STATE_64_T __uint128_t 61 #endif // LEHMER64 62 63 #ifdef WYHASH64 64 #define PRNG_NAME_64 wyhash64 65 #define PRNG_STATE_64_T uint64_t 66 #endif // LEHMER64 67 68 #ifdef XORSHIFT_13_7_17 69 #define PRNG_NAME_64 xorshift_13_7_17 70 #define PRNG_STATE_64_T uint64_t 71 #endif // XORSHIFT_13_7_17 72 73 #ifdef XORSHIFT_6_21_7 74 #define PRNG_NAME_32 xorshift_6_21_7 75 #define PRNG_STATE_32_T uint32_t 76 #endif // XORSHIFT_6_21_7 77 78 #ifdef XORSHIFT_12_25_27 79 #define PRNG_NAME_64 xorshift_12_25_27 80 #define PRNG_STATE_64_T uint64_t 81 #endif // XORSHIFT_12_25_27 82 83 #ifdef KISS_64 84 #define PRNG_NAME_64 kiss_64 85 #define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t) 86 typedef struct PRNG_STATE_64_T { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T; 87 #endif // KISS_^64 88 89 #ifdef XORWOW 90 #define PRNG_NAME_32 xorwow 91 #define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t) 92 typedef struct PRNG_STATE_32_T { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T; 93 #endif // XOSHIRO128PP 94 95 #define PRNG_SET_SEED_64 GLUE(PRNG_NAME_64,_set_seed) 96 #define PRNG_SET_SEED_32 GLUE(PRNG_NAME_32,_set_seed) 97 98 99 // Default PRNG used by runtime. 100 #ifdef __x86_64__ // 64-bit architecture 101 #define PRNG_NAME PRNG_NAME_64 102 #define PRNG_STATE_T PRNG_STATE_64_T 103 #else // 32-bit architecture 104 #define PRNG_NAME PRNG_NAME_32 105 #define PRNG_STATE_T PRNG_STATE_32_T 106 #endif // __x86_64__ 107 108 #define PRNG_SET_SEED GLUE(PRNG_NAME,_set_seed) 109 110 111 // ALL PRNG ALGORITHMS ARE OPTIMIZED SO THAT THE PRNG LOGIC CAN HAPPEN IN PARALLEL WITH THE USE OF THE RESULT. 112 // Therefore, the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the 113 // first random value. 114 115 #ifdef __cforall // don't include in C code (invoke.h) 116 117 // https://prng.di.unimi.it/xoshiro256starstar.c 118 // 119 // This is xoshiro256++ 1.0, one of our all-purpose, rock-solid generators. It has excellent (sub-ns) speed, a state 120 // (256 bits) that is large enough for any parallel application, and it passes all tests we are aware of. 121 // 122 // For generating just floating-point numbers, xoshiro256+ is even faster. 123 // 124 // The state must be seeded so that it is not everywhere zero. If you have a 64-bit seed, we suggest to seed a 125 // splitmix64 generator and use its output to fill s. 126 127 #ifndef XOSHIRO256PP 128 typedef struct xoshiro256pp_t { uint64_t s[4]; } xoshiro256pp_t; 129 #endif // ! XOSHIRO256PP 130 131 static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) { 132 inline uint64_t rotl(const uint64_t x, int k) { 133 return (x << k) | (x >> (64 - k)); 134 } // rotl 135 136 const uint64_t result = rotl( s[0] + s[3], 23 ) + s[0]; 137 const uint64_t t = s[1] << 17; 138 139 s[2] ^= s[0]; 140 s[3] ^= s[1]; 141 s[1] ^= s[2]; 142 s[0] ^= s[3]; 143 s[2] ^= t; 144 s[3] = rotl( s[3], 45 ); 145 return result; 146 } // xoshiro256pp 147 148 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) { 149 state = (xoshiro256pp_t){ {seed, seed, seed, seed} }; 150 xoshiro256pp( state ); 151 } // xoshiro256pp_set_seed 152 153 // https://prng.di.unimi.it/xoshiro128plusplus.c 154 // 155 // This is xoshiro128++ 1.0, one of our 32-bit all-purpose, rock-solid generators. It has excellent speed, a state size 156 // (128 bits) that is large enough for mild parallelism, and it passes all tests we are aware of. 157 // 158 // For generating just single-precision (i.e., 32-bit) floating-point numbers, xoshiro128+ is even faster. 159 // 160 // The state must be seeded so that it is not everywhere zero. 161 162 #ifndef XOSHIRO128PP 163 typedef struct xoshiro128pp_t { uint32_t s[4]; } xoshiro128pp_t; 164 #endif // ! XOSHIRO128PP 165 166 static inline uint32_t xoshiro128pp( xoshiro128pp_t & rs ) with(rs) { 167 inline uint32_t rotl( const uint32_t x, int k ) { 168 return (x << k) | (x >> (32 - k)); 169 } // rotl 170 171 const uint32_t result = rotl( s[0] + s[3], 7 ) + s[0]; 172 const uint32_t t = s[1] << 9; 173 174 s[2] ^= s[0]; 175 s[3] ^= s[1]; 176 s[1] ^= s[2]; 177 s[0] ^= s[3]; 178 s[2] ^= t; 179 s[3] = rotl( s[3], 11 ); 180 return result; 181 } // xoshiro128pp 182 183 static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) { 184 state = (xoshiro128pp_t){ {seed, seed, seed, seed} }; 185 xoshiro128pp( state ); // prime 186 } // xoshiro128pp_set_seed 187 188 #ifdef __SIZEOF_INT128__ 189 // Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is 190 // returned (copied), and then compute and store the next random value. 191 //-------------------------------------------------- 23 #if defined(__SIZEOF_INT128__) 24 //-------------------------------------------------- 192 25 static inline uint64_t lehmer64( __uint128_t & state ) { 193 26 __uint128_t ret = state; 194 27 state *= 0xda942042e4dd58b5; 195 28 return ret >> 64; 196 } // lehmer6429 } 197 30 198 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) { 199 state = seed; 200 lehmer64( state ); 201 } // lehmer64_set_seed 202 203 //-------------------------------------------------- 31 //-------------------------------------------------- 204 32 static inline uint64_t wyhash64( uint64_t & state ) { 205 uint64_t ret = state; 206 state += 0x_60be_e2be_e120_fc15; 33 state += 0x60bee2bee120fc15; 207 34 __uint128_t tmp; 208 tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d;35 tmp = (__uint128_t) state * 0xa3b195354a39b70d; 209 36 uint64_t m1 = (tmp >> 64) ^ tmp; 210 tmp = (__uint128_t)m1 * 0x _1b03_7387_12fa_d5c9;37 tmp = (__uint128_t)m1 * 0x1b03738712fad5c9; 211 38 uint64_t m2 = (tmp >> 64) ^ tmp; 212 39 return m2; 213 } // wyhash64 214 215 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) { 216 state = seed; 217 wyhash64( state ); // prime 218 } // wyhash64_set_seed 219 #endif // __SIZEOF_INT128__ 40 } 41 #endif 220 42 221 43 //-------------------------------------------------- … … 226 48 state ^= state << 17; 227 49 return ret; 228 } // xorshift_13_7_17 229 230 static inline void xorshift_13_7_17_set_seed( uint64_t & state, uint64_t seed ) { 231 state = seed; 232 xorshift_13_7_17( state ); // prime 233 } // xorshift_13_7_17_set_seed 50 } 234 51 235 52 //-------------------------------------------------- 236 // Marsaglia shift-XOR PRNG with thread-local state237 // Period is 4G-1238 // 0 is absorbing and must be avoided239 // Low-order bits are not particularly random240 53 static inline uint32_t xorshift_6_21_7( uint32_t & state ) { 241 54 uint32_t ret = state; … … 246 59 } // xorshift_6_21_7 247 60 248 static inline void xorshift_6_21_7_set_seed( uint32_t & state, uint32_t seed ) { 249 state = seed; 250 xorshift_6_21_7( state ); // prime 251 } // xorshift_6_21_7_set_seed 61 //-------------------------------------------------- 62 typedef struct { 63 uint32_t a, b, c, d; 64 uint32_t counter; 65 } xorwow__state_t; 252 66 253 //-------------------------------------------------- 254 // The state must be seeded with a nonzero value. 255 static inline uint64_t xorshift_12_25_27( uint64_t & state ) { 256 uint64_t ret = state; 257 state ^= state >> 12; 258 state ^= state << 25; 259 state ^= state >> 27; 260 return ret * 0x_2545_F491_4F6C_DD1D; 261 } // xorshift_12_25_27 67 // The state array must be initialized to not be all zero in the first four words. 68 static inline uint32_t xorwow( xorwow__state_t & state ) { 69 // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs". 70 uint32_t ret = state.a + state.counter; 71 uint32_t t = state.d; 262 72 263 static inline void xorshift_12_25_27_set_seed( uint64_t & state, uint64_t seed ) { 264 state = seed; 265 xorshift_12_25_27( state ); // prime 266 } // xorshift_12_25_27_set_seed 267 268 //-------------------------------------------------- 269 // The state must be seeded with a nonzero value. 270 #ifndef KISS_64 271 typedef struct kiss_64_t { uint64_t z, w, jsr, jcong; } kiss_64_t; 272 #endif // ! KISS_64 273 274 static inline uint64_t kiss_64( kiss_64_t & state ) with(state) { 275 kiss_64_t ret = state; 276 z = 36969 * (z & 65535) + (z >> 16); 277 w = 18000 * (w & 65535) + (w >> 16); 278 jsr ^= (jsr << 17); 279 jsr ^= (jsr << 13); 280 jsr ^= (jsr << 5); 281 jcong = 69069 * jcong + 1234567; 282 return (((ret.z << 16) + ret.w) ^ ret.jcong) + ret.jsr; 283 } // kiss_64 284 285 static inline void kiss_64_set_seed( kiss_64_t & state, uint64_t seed ) with(state) { 286 z = 1; w = 1; jsr = 4; jcong = seed; 287 kiss_64( state ); // prime 288 } // kiss_64_set_seed 289 290 //-------------------------------------------------- 291 // The state array must be initialized to non-zero in the first four words. 292 #ifndef XORWOW 293 typedef struct xorwow_t { uint32_t a, b, c, d, counter; } xorwow_t; 294 #endif // ! XORWOW 295 296 static inline uint32_t xorwow( xorwow_t & state ) with(state) { 297 // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs". 298 uint32_t ret = a + counter; 299 uint32_t t = d; 300 301 uint32_t const s = a; 302 d = c; 303 c = b; 304 b = s; 73 uint32_t const s = state.a; 74 state.d = state.c; 75 state.c = state.b; 76 state.b = s; 305 77 306 78 t ^= t >> 2; 307 79 t ^= t << 1; 308 80 t ^= s ^ (s << 4); 309 a = t; 310 counter += 362437; 81 state.a = t; 82 83 state.counter += 362437; 311 84 return ret; 312 } // xorwow 313 314 static inline void xorwow_set_seed( xorwow_t & state, uint32_t seed ) { 315 state = (xorwow_t){ seed, seed, seed, seed, 0 }; 316 xorwow( state ); // prime 317 } // xorwow_set_seed 85 } 318 86 319 87 //-------------------------------------------------- 320 // Used in __tls_rand_fwd 88 static inline uint32_t LCG( uint32_t & state ) { // linear congruential generator 89 uint32_t ret = state; 90 state = 36969 * (state & 65535) + (state >> 16); // 36969 is NOT prime! No not change it! 91 return ret; 92 } // LCG 93 94 //-------------------------------------------------- 321 95 #define M (1_l64u << 48_l64u) 322 96 #define A (25214903917_l64u) … … 329 103 state = (A * state + C) & (M - 1); 330 104 return state >> D; 331 } // LCGBI_fwd105 } 332 106 333 107 static inline uint32_t LCGBI_bck( uint64_t & state ) { … … 335 109 state = AI * (state - C) & (M - 1); 336 110 return r; 337 } // LCGBI_bck111 } 338 112 339 113 #undef M … … 342 116 #undef C 343 117 #undef D 344 345 #endif // __cforall
Note:
See TracChangeset
for help on using the changeset viewer.