Changeset b797d97 for libcfa


Ignore:
Timestamp:
Dec 21, 2022, 9:21:15 PM (18 months ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
ADT, ast-experimental, master
Children:
ae7a085c
Parents:
6b608c7
Message:

formatting, switch to XOSHIRO256PP/XOSHIRO128PP as the 64/32-bit default PRNG, fix kiss_64 shifts

File:
1 edited

Legend:

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

    r6b608c7 rb797d97  
    1010// Created On       : Fri Jan 14 07:18:11 2022
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Dec 11 18:43:58 2022
    13 // Update Count     : 171
     12// Last Modified On : Wed Dec 14 20:32:53 2022
     13// Update Count     : 177
    1414//
    1515
     
    2424#ifdef __x86_64__                                                                               // 64-bit architecture
    2525        // 64-bit generators
    26         #define LEHMER64
     26        //#define LEHMER64
    2727        //#define XORSHIFT_12_25_27
    28         //#define XOSHIRO256PP
     28        #define XOSHIRO256PP
    2929        //#define KISS_64
    3030
    3131        // 32-bit generators
    32         #define XORSHIFT_6_21_7
    33         //#define XOSHIRO128PP
     32        //#define XORSHIFT_6_21_7
     33        #define XOSHIRO128PP
    3434#else                                                                                                   // 32-bit architecture
    3535        // 64-bit generators
    36         #define XORSHIFT_13_7_17
     36        //#define XORSHIFT_13_7_17
     37        #define XOSHIRO256PP
    3738
    3839        // 32-bit generators
    39         #define XORSHIFT_6_21_7
     40        //#define XORSHIFT_6_21_7
     41        #define XOSHIRO128PP
    4042#endif // __x86_64__
    4143
     
    4749#define PRNG_NAME_64 xoshiro256pp
    4850#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;
     51typedef struct PRNG_STATE_64_T { uint64_t s0, s1, s2, s3; } PRNG_STATE_64_T;
    5052#endif // XOSHIRO256PP
    5153
     
    5355#define PRNG_NAME_32 xoshiro128pp
    5456#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;
     57typedef struct PRNG_STATE_32_T { uint32_t s0, s1, s2, s3; } PRNG_STATE_32_T;
    5658#endif // XOSHIRO128PP
    5759
     
    110112
    111113// 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// Specifically, the current random state is copied for returning, before computing the next value.  As a consequence,
     115// the set_seed routine primes the PRNG by calling it with the state so the seed is not return as the first random
     116// value.
     117
    114118
    115119#ifdef __cforall                                                                                // don't include in C code (invoke.h)
     
    126130
    127131#ifndef XOSHIRO256PP
    128 typedef struct xoshiro256pp_t { uint64_t s[4]; } xoshiro256pp_t;
     132typedef struct xoshiro256pp_t { uint64_t s0, s1, s2, s3; } xoshiro256pp_t;
    129133#endif // ! XOSHIRO256PP
    130134
    131135static inline uint64_t xoshiro256pp( xoshiro256pp_t & rs ) with(rs) {
    132         inline uint64_t rotl(const uint64_t x, int k) {
     136        inline uint64_t rotl( const uint64_t x, int k ) {
    133137                return (x << k) | (x >> (64 - k));
    134138        } // rotl
    135139
    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 );
     140        const uint64_t result = rotl( s0 + s3, 23 ) + s0;
     141        const uint64_t t = s1 << 17;
     142
     143        s2 ^= s0;
     144        s3 ^= s1;
     145        s1 ^= s2;
     146        s0 ^= s3;
     147        s2 ^= t;
     148        s3 = rotl( s3, 45 );
    145149        return result;
    146150} // xoshiro256pp
    147151
    148 static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state,  uint64_t seed ) {
    149         state = (xoshiro256pp_t){ {seed, seed, seed, seed} };
     152static inline void xoshiro256pp_set_seed( xoshiro256pp_t & state, uint64_t seed ) {
     153        state = (xoshiro256pp_t){ seed, seed, seed, seed };
    150154        xoshiro256pp( state );
    151155} // xoshiro256pp_set_seed
     
    161165
    162166#ifndef XOSHIRO128PP
    163 typedef struct xoshiro128pp_t { uint32_t s[4]; } xoshiro128pp_t;
     167typedef struct xoshiro128pp_t { uint32_t s0, s1, s2, s3; } xoshiro128pp_t;
    164168#endif // ! XOSHIRO128PP
    165169
     
    169173        } // rotl
    170174
    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 );
     175        const uint32_t result = rotl( s0 + s3, 7 ) + s0;
     176        const uint32_t t = s1 << 9;
     177
     178        s2 ^= s0;
     179        s3 ^= s1;
     180        s1 ^= s2;
     181        s0 ^= s3;
     182        s2 ^= t;
     183        s3 = rotl( s3, 11 );
    180184        return result;
    181185} // xoshiro128pp
    182186
    183187static inline void xoshiro128pp_set_seed( xoshiro128pp_t & state, uint32_t seed ) {
    184         state = (xoshiro128pp_t){ {seed, seed, seed, seed} };
     188        state = (xoshiro128pp_t){ seed, seed, seed, seed };
    185189        xoshiro128pp( state );                                                          // prime
    186190} // xoshiro128pp_set_seed
    187191
    188192#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.
    191193        //--------------------------------------------------
    192194        static inline uint64_t lehmer64( __uint128_t & state ) {
     
    197199
    198200        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 argest period, so no factors of 2 in the seed.
    199202                state = seed;
    200                 lehmer64( state );
     203                lehmer64( state );                                                              // prime
    201204        } // lehmer64_set_seed
    202205
     
    272275#endif // ! KISS_64
    273276
    274 static inline uint64_t kiss_64( kiss_64_t & state ) with(state) {
    275         kiss_64_t ret = state;
     277static inline uint64_t kiss_64( kiss_64_t & rs ) with(rs) {
     278        kiss_64_t ret = rs;
    276279        z = 36969 * (z & 65535) + (z >> 16);
    277280        w = 18000 * (w & 65535) + (w >> 16);
    278         jsr ^= (jsr << 17);
    279281        jsr ^= (jsr << 13);
     282        jsr ^= (jsr >> 17);
    280283        jsr ^= (jsr << 5);
    281284        jcong = 69069 * jcong + 1234567;
     
    283286} // kiss_64
    284287
    285 static inline void kiss_64_set_seed( kiss_64_t & state, uint64_t seed ) with(state) {
     288static inline void kiss_64_set_seed( kiss_64_t & rs, uint64_t seed ) with(rs) {
    286289        z = 1; w = 1; jsr = 4; jcong = seed;
    287         kiss_64( state );                                                                       // prime
     290        kiss_64( rs );                                                                          // prime
    288291} // kiss_64_set_seed
    289292
     
    294297#endif // ! XORWOW
    295298
    296 static inline uint32_t xorwow( xorwow_t & state ) with(state) {
     299static inline uint32_t xorwow( xorwow_t & rs ) with(rs) {
    297300        // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs".
    298301        uint32_t ret = a + counter;
     
    312315} // xorwow
    313316
    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
     317static inline void xorwow_set_seed( xorwow_t & rs, uint32_t seed ) {
     318        rs = (xorwow_t){ seed, seed, seed, seed, 0 };
     319        xorwow( rs );                                                                           // prime
    317320} // xorwow_set_seed
    318321
     
    326329
    327330// Bi-directional LCG random-number generator
    328 static inline uint32_t LCGBI_fwd( uint64_t & state ) {
    329         state = (A * state + C) & (M - 1);
    330         return state >> D;
     331static inline uint32_t LCGBI_fwd( uint64_t & rs ) {
     332        rs = (A * rs + C) & (M - 1);
     333        return rs >> D;
    331334} // LCGBI_fwd
    332335
    333 static inline uint32_t LCGBI_bck( uint64_t & state ) {
    334         unsigned int r = state >> D;
    335         state = AI * (state - C) & (M - 1);
     336static inline uint32_t LCGBI_bck( uint64_t & rs ) {
     337        unsigned int r = rs >> D;
     338        rs = AI * (rs - C) & (M - 1);
    336339        return r;
    337340} // LCGBI_bck
Note: See TracChangeset for help on using the changeset viewer.