Changeset 90fb672 for libcfa/src/bits/random.hfa
 Timestamp:
 Mar 21, 2023, 7:44:45 AM (19 months ago)
 Branches:
 ADT, astexperimental, master
 Children:
 1205b3e
 Parents:
 12b006c
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

libcfa/src/bits/random.hfa
r12b006c r90fb672 10 10 // Created On : Fri Jan 14 07:18:11 2022 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Mon Mar 20 10:01:40202313 // Update Count : 18 012 // Last Modified On : Mon Mar 20 21:45:24 2023 13 // Update Count : 186 14 14 // 15 15 … … 131 131 #ifdef __cforall // don't include in C code (invoke.h) 132 132 133 // Splitmix64134 133 // https://rosettacode.org/wiki/Pseudorandom_numbers/Splitmix64 135 // Splitmix64 is not recommended for demanding random number requirements, 136 // but is often used to calculate initial states for other more complex 137 // pseudorandom number generators. 134 // 135 // Splitmix64 is not recommended for demanding random number requirements, but is often used to calculate initial states 136 // for other more complex pseudorandom number generators (see https://prng.di.unimi.it). 137 // Also https://rosettacode.org/wiki/Pseudorandom_numbers/Splitmix64. 138 138 static inline uint64_t splitmix64( uint64_t & state ) { 139 139 state += 0x9e3779b97f4a7c15; … … 149 149 } // splitmix64_set_seed 150 150 151 // Splitmix32152 151 // https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32 153 // Splitmix32 is not recommended for demanding random number requirements,154 // but is often used to calculate initial states for other more complex155 // pseudorandom number generators.156 // SplitMix32 is a 32 bit variant of Splitmix64 152 // 153 // Splitmix32 is not recommended for demanding random number requirements, but is often used to calculate initial states 154 // for other more complex pseudorandom number generators (see https://prng.di.unimi.it). 155 157 156 static inline uint32_t splitmix32( uint32_t & state ) { 158 157 state += 0x9e3779b9; … … 169 168 170 169 #ifdef __SIZEOF_INT128__ 171 // 172 static inline uint64_t lehmer64( __uint128_t & state ) { 173 __uint128_t ret = state; 174 state *= 0x_da94_2042_e4dd_58b5; 175 return ret >> 64; 176 } // lehmer64 177 178 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) { 179 // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed. 180 state = seed; 181 lehmer64( state ); // prime 182 } // lehmer64_set_seed 183 184 // 185 static inline uint64_t wyhash64( uint64_t & state ) { 186 uint64_t ret = state; 187 state += 0x_60be_e2be_e120_fc15; 188 __uint128_t tmp; 189 tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d; 190 uint64_t m1 = (tmp >> 64) ^ tmp; 191 tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9; 192 uint64_t m2 = (tmp >> 64) ^ tmp; 193 return m2; 194 } // wyhash64 170 // 171 static inline uint64_t lehmer64( __uint128_t & state ) { 172 __uint128_t ret = state; 173 state *= 0x_da94_2042_e4dd_58b5; 174 return ret >> 64; 175 } // lehmer64 176 177 static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) { 178 // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed. 179 state = splitmix64( seed ); // prime 180 } // lehmer64_set_seed 181 182 // 183 static inline uint64_t wyhash64( uint64_t & state ) { 184 uint64_t ret = state; 185 state += 0x_60be_e2be_e120_fc15; 186 __uint128_t tmp; 187 tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d; 188 uint64_t m1 = (tmp >> 64) ^ tmp; 189 tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9; 190 uint64_t m2 = (tmp >> 64) ^ tmp; 191 return m2; 192 } // wyhash64 193 194 static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) { 195 state = splitmix64( seed ); // prime 196 } // wyhash64_set_seed 195 197 #endif // __SIZEOF_INT128__ 196 198 … … 227 229 228 230 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) { 229 // these are done explicitly in this order to attain repeatable seeding. 230 // do not call splitmix64 directly in the state init since order of argument evaluation 231 // may not be consistent leading to irreproducible seeding 232 uint64_t seed1 = splitmix64( seed ); 231 // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined. 232 uint64_t seed1 = splitmix64( seed ); // prime 233 233 uint64_t seed2 = splitmix64( seed ); 234 234 uint64_t seed3 = splitmix64( seed ); 235 235 uint64_t seed4 = splitmix64( seed ); 236 236 state = (xoshiro256pp_t){ seed1, seed2, seed3, seed4 }; 237 xoshiro256pp( state ); // prime238 237 } // xoshiro256pp_set_seed 239 238 … … 269 268 270 269 static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) { 271 // these are done explicitly in this order to attain repeatable seeding. 272 // do not call splitmix32 directly in the state init since order of argument evaluation 273 // may not be consistent leading to irreproducible seeding 274 uint32_t seed1 = splitmix32( seed ); 270 // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined. 271 uint32_t seed1 = splitmix32( seed ); // prime 275 272 uint32_t seed2 = splitmix32( seed ); 276 273 uint32_t seed3 = splitmix32( seed ); 277 274 uint32_t seed4 = splitmix32( seed ); 278 275 state = (xoshiro128pp_t){ seed1, seed2, seed3, seed4 }; 279 xoshiro128pp( state ); // prime280 276 } // xoshiro128pp_set_seed 281 277 … … 290 286 291 287 static inline void xorshift_13_7_17_set_seed( uint64_t & state, uint64_t seed ) { 292 state = seed; 293 xorshift_13_7_17( state ); // prime 288 state = splitmix64( seed ); // prime 294 289 } // xorshift_13_7_17_set_seed 295 290 … … 308 303 309 304 static inline void xorshift_6_21_7_set_seed( uint32_t & state, uint32_t seed ) { 310 state = seed; 311 xorshift_6_21_7( state ); // prime 305 state = splitmix32( seed ); // prime 312 306 } // xorshift_6_21_7_set_seed 313 307 … … 323 317 324 318 static inline void xorshift_12_25_27_set_seed( uint64_t & state, uint64_t seed ) { 325 state = seed; 326 xorshift_12_25_27( state ); // prime 319 state = splitmix64( seed ); // prime 327 320 } // xorshift_12_25_27_set_seed 328 321 … … 345 338 346 339 static inline void kiss_64_set_seed( kiss_64_t & rs, uint64_t seed ) with(rs) { 347 z = 1; w = 1; jsr = 4; jcong = seed; 348 kiss_64( rs ); // prime 340 z = 1; w = 1; jsr = 4; jcong = splitmix64( seed ); // prime 349 341 } // kiss_64_set_seed 350 342 … … 374 366 375 367 static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) { 376 // these are done explicitly in this order to attain repeatable seeding. 377 // do not call splitmix32 directly in the state init since order of argument evaluation 378 // may not be consistent leading to irreproducible seeding 379 uint32_t seed1 = splitmix32( seed ); 368 // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined. 369 uint32_t seed1 = splitmix32( seed ); // prime 380 370 uint32_t seed2 = splitmix32( seed ); 381 371 uint32_t seed3 = splitmix32( seed ); 382 372 uint32_t seed4 = splitmix32( seed ); 383 373 rs = (xorwow_t){ seed1, seed2, seed3, seed4, 0 }; 384 xorwow( rs ); // prime385 374 } // xorwow_set_seed 386 375 … … 388 377 // Used in __tls_rand_fwd 389 378 #define M (1_l64u << 48_l64u) 390 #define A (25 214903917_l64u)391 #define AI (18 446708753438544741_l64u)379 #define A (25_214_903_917_l64u) 380 #define AI (18_446_708_753_438_544_741_l64u) 392 381 #define C (11_l64u) 393 382 #define D (16_l64u)
Note: See TracChangeset
for help on using the changeset viewer.