Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/bits/random.hfa

    r90fb672 rd9585291  
    1010// Created On       : Fri Jan 14 07:18:11 2022
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Mar 20 21:45:24 2023
    13 // Update Count     : 186
     12// Last Modified On : Thu Dec 22 20:54:22 2022
     13// Update Count     : 178
    1414//
    1515
     
    2828        #define XOSHIRO256PP
    2929        //#define KISS_64
    30     // #define SPLITMIX_64
    3130
    3231        // 32-bit generators
    3332        //#define XORSHIFT_6_21_7
    3433        #define XOSHIRO128PP
    35     // #define SPLITMIX_32
    3634#else                                                                                                   // 32-bit architecture
    3735        // 64-bit generators
    3836        //#define XORSHIFT_13_7_17
    3937        #define XOSHIRO256PP
    40     // #define SPLITMIX_64
    4138
    4239        // 32-bit generators
    4340        //#define XORSHIFT_6_21_7
    4441        #define XOSHIRO128PP
    45     // #define SPLITMIX_32
    4642#endif // __x86_64__
    4743
    4844// Define C/CFA PRNG name and random-state.
     45
     46// SKULLDUGGERY: typedefs name struct and typedef with the same name to deal with CFA typedef numbering problem.
    4947
    5048#ifdef XOSHIRO256PP
    5149#define PRNG_NAME_64 xoshiro256pp
    5250#define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t)
    53 typedef struct { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T;
     51typedef struct PRNG_STATE_64_T { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T;
    5452#endif // XOSHIRO256PP
    5553
     
    5755#define PRNG_NAME_32 xoshiro128pp
    5856#define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t)
    59 typedef struct { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T;
     57typedef struct PRNG_STATE_32_T { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T;
    6058#endif // XOSHIRO128PP
    6159
     
    8583#endif // XORSHIFT_12_25_27
    8684
    87 #ifdef SPLITMIX_64
    88 #define PRNG_NAME_64 splitmix64
    89 #define PRNG_STATE_64_T uint64_t
    90 #endif // SPLITMIX32
    91 
    92 #ifdef SPLITMIX_32
    93 #define PRNG_NAME_32 splitmix32
    94 #define PRNG_STATE_32_T uint32_t
    95 #endif // SPLITMIX32
    96 
    9785#ifdef KISS_64
    9886#define PRNG_NAME_64 kiss_64
    9987#define PRNG_STATE_64_T GLUE(PRNG_NAME_64,_t)
    100 typedef struct { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T;
     88typedef struct PRNG_STATE_64_T { uint64_t z, w, jsr, jcong; } PRNG_STATE_64_T;
    10189#endif // KISS_^64
    10290
     
    10492#define PRNG_NAME_32 xorwow
    10593#define PRNG_STATE_32_T GLUE(PRNG_NAME_32,_t)
    106 typedef struct { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T;
     94typedef struct PRNG_STATE_32_T { uint32_t a, b, c, d, counter; } PRNG_STATE_32_T;
    10795#endif // XOSHIRO128PP
    10896
     
    131119#ifdef __cforall                                                                                // don't include in C code (invoke.h)
    132120
    133 // https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64
    134 //
    135 // Splitmix64 is not recommended for demanding random number requirements, but is often used to calculate initial states
    136 // for other more complex pseudo-random number generators (see https://prng.di.unimi.it).
    137 // Also https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64.
    138 static inline uint64_t splitmix64( uint64_t & state ) {
    139     state += 0x9e3779b97f4a7c15;
    140     uint64_t z = state;
    141     z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
    142     z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
    143     return z ^ (z >> 31);
    144 } // splitmix64
    145 
    146 static inline void splitmix64_set_seed( uint64_t & state , uint64_t seed ) {
    147     state = seed;
    148     splitmix64( state );                                                                // prime
    149 } // splitmix64_set_seed
    150 
    151 // https://github.com/bryc/code/blob/master/jshash/PRNGs.md#splitmix32
    152 //
    153 // Splitmix32 is not recommended for demanding random number requirements, but is often used to calculate initial states
    154 // for other more complex pseudo-random number generators (see https://prng.di.unimi.it).
    155 
    156 static inline uint32_t splitmix32( uint32_t & state ) {
    157     state += 0x9e3779b9;
    158     uint64_t z = state;
    159     z = (z ^ (z >> 15)) * 0x85ebca6b;
    160     z = (z ^ (z >> 13)) * 0xc2b2ae35;
    161     return z ^ (z >> 16);
    162 } // splitmix32
    163 
    164 static inline void splitmix32_set_seed( uint32_t & state, uint64_t seed ) {
    165     state = seed;
    166     splitmix32( state );                                                                // prime
    167 } // splitmix32_set_seed
    168 
    169 #ifdef __SIZEOF_INT128__
    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
    197 #endif // __SIZEOF_INT128__
    198 
    199121// https://prng.di.unimi.it/xoshiro256starstar.c
    200122//
     
    208130
    209131#ifndef XOSHIRO256PP
    210 typedef struct { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
     132typedef struct xoshiro256pp_t { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
    211133#endif // ! XOSHIRO256PP
    212134
     
    229151
    230152static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t 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     uint64_t seed2 = splitmix64( seed );
    234     uint64_t seed3 = splitmix64( seed );
    235     uint64_t seed4 = splitmix64( seed );
    236         state = (xoshiro256pp_t){ seed1, seed2, seed3, seed4 };
     153        state = (xoshiro256pp_t){ seed, seed, seed, seed };
     154        xoshiro256pp( state );
    237155} // xoshiro256pp_set_seed
    238156
     
    247165
    248166#ifndef XOSHIRO128PP
    249 typedef struct { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
     167typedef struct xoshiro128pp_t { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
    250168#endif // ! XOSHIRO128PP
    251169
     
    268186
    269187static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) {
    270     // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined.
    271     uint32_t seed1 = splitmix32( seed );                                // prime
    272     uint32_t seed2 = splitmix32( seed );
    273     uint32_t seed3 = splitmix32( seed );
    274     uint32_t seed4 = splitmix32( seed );
    275         state = (xoshiro128pp_t){ seed1, seed2, seed3, seed4 };
     188        state = (xoshiro128pp_t){ seed, seed, seed, seed };
     189        xoshiro128pp( state );                                                          // prime
    276190} // xoshiro128pp_set_seed
     191
     192#ifdef __SIZEOF_INT128__
     193        //--------------------------------------------------
     194        static inline uint64_t lehmer64( __uint128_t & state ) {
     195                __uint128_t ret = state;
     196                state *= 0x_da94_2042_e4dd_58b5;
     197                return ret >> 64;
     198        } // lehmer64
     199
     200        static inline void lehmer64_set_seed( __uint128_t & state, uint64_t seed ) {
     201                // The seed needs to be coprime with the 2^64 modulus to get the largest period, so no factors of 2 in the seed.
     202                state = seed;
     203                lehmer64( state );                                                              // prime
     204        } // lehmer64_set_seed
     205
     206        //--------------------------------------------------
     207        static inline uint64_t wyhash64( uint64_t & state ) {
     208                uint64_t ret = state;
     209                state += 0x_60be_e2be_e120_fc15;
     210                __uint128_t tmp;
     211                tmp = (__uint128_t) ret * 0x_a3b1_9535_4a39_b70d;
     212                uint64_t m1 = (tmp >> 64) ^ tmp;
     213                tmp = (__uint128_t)m1 * 0x_1b03_7387_12fa_d5c9;
     214                uint64_t m2 = (tmp >> 64) ^ tmp;
     215                return m2;
     216        } // wyhash64
     217
     218        static inline void wyhash64_set_seed( uint64_t & state, uint64_t seed ) {
     219                state = seed;
     220                wyhash64( state );                                                              // prime
     221        } // wyhash64_set_seed
     222#endif // __SIZEOF_INT128__
    277223
    278224//--------------------------------------------------
     
    286232
    287233static inline void xorshift_13_7_17_set_seed( uint64_t & state, uint64_t seed ) {
    288         state = splitmix64( seed );                                                     // prime
     234        state = seed;
     235        xorshift_13_7_17( state );                                                      // prime
    289236} // xorshift_13_7_17_set_seed
    290237
     
    303250
    304251static inline void xorshift_6_21_7_set_seed( uint32_t & state, uint32_t seed ) {
    305     state = splitmix32( seed );                                                 // prime
     252        state = seed;
     253        xorshift_6_21_7( state );                                                       // prime
    306254} // xorshift_6_21_7_set_seed
    307255
     
    317265
    318266static inline void xorshift_12_25_27_set_seed( uint64_t & state, uint64_t seed ) {
    319         state = splitmix64( seed );                                                     // prime
     267        state = seed;
     268        xorshift_12_25_27( state );                                                     // prime
    320269} // xorshift_12_25_27_set_seed
    321270
     
    323272// The state must be seeded with a nonzero value.
    324273#ifndef KISS_64
    325 typedef struct { uint64_t z, w, jsr, jcong; } kiss_64_t;
     274typedef struct kiss_64_t { uint64_t z, w, jsr, jcong; } kiss_64_t;
    326275#endif // ! KISS_64
    327276
     
    338287
    339288static inline void kiss_64_set_seed( kiss_64_t & rs, uint64_t seed ) with(rs) {
    340         z = 1; w = 1; jsr = 4; jcong = splitmix64( seed );      // prime
     289        z = 1; w = 1; jsr = 4; jcong = seed;
     290        kiss_64( rs );                                                                          // prime
    341291} // kiss_64_set_seed
    342292
     
    344294// The state array must be initialized to non-zero in the first four words.
    345295#ifndef XORWOW
    346 typedef struct { uint32_t a, b, c, d, counter; } xorwow_t;
     296typedef struct xorwow_t { uint32_t a, b, c, d, counter; } xorwow_t;
    347297#endif // ! XORWOW
    348298
     
    366316
    367317static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) {
    368     // To attain repeatable seeding, compute seeds separately because the order of argument evaluation is undefined.
    369     uint32_t seed1 = splitmix32( seed );                                // prime
    370     uint32_t seed2 = splitmix32( seed );
    371     uint32_t seed3 = splitmix32( seed );
    372     uint32_t seed4 = splitmix32( seed );
    373         rs = (xorwow_t){ seed1, seed2, seed3, seed4, 0 };
     318        rs = (xorwow_t){ seed, seed, seed, seed, 0 };
     319        xorwow( rs );                                                                           // prime
    374320} // xorwow_set_seed
    375321
     
    377323// Used in __tls_rand_fwd
    378324#define M  (1_l64u << 48_l64u)
    379 #define A  (25_214_903_917_l64u)
    380 #define AI (18_446_708_753_438_544_741_l64u)
     325#define A  (25214903917_l64u)
     326#define AI (18446708753438544741_l64u)
    381327#define C  (11_l64u)
    382328#define D  (16_l64u)
Note: See TracChangeset for help on using the changeset viewer.