source: libcfa/src/bits/random.hfa @ d2ad151

ADTast-experimental
Last change on this file since d2ad151 was d2ad151, checked in by Peter A. Buhr <pabuhr@…>, 18 months ago

major update of PRNG

  • Property mode set to 100644
File size: 3.4 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// random.hfa --
8//
9// Author           : Peter A. Buhr
10// Created On       : Fri Jan 14 07:18:11 2022
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Sat Nov 19 17:47:43 2022
13// Update Count     : 8
14//
15
16#pragma once
17
18#include <stdint.h>
19
20#ifdef __x86_64__                                                                               // 64-bit architecture
21#define LEHMER64
22#else                                                                                                   // 32-bit architecture
23#define XORSHIFT_6_21_7
24#endif // __x86_64__
25
26// Pipelined to allow out-of-order overlap with reduced dependencies. Critically, the current random state is returned
27// (copied), and then compute and store the next random value.
28
29#if defined(__SIZEOF_INT128__)
30//--------------------------------------------------
31        #ifdef LEHMER64
32        #define PRNG_ARG_T __uint128_t
33        #define PRNG_NAME lehmer64
34        #endif // LEHMER64
35
36        static inline uint64_t lehmer64( __uint128_t & state ) {
37                __uint128_t ret = state;
38                state *= 0xda942042e4dd58b5;
39                return ret >> 64;
40        }
41
42//--------------------------------------------------
43        static inline uint64_t wyhash64( uint64_t & state ) {
44                state += 0x60bee2bee120fc15;
45                __uint128_t tmp;
46                tmp = (__uint128_t) state * 0xa3b195354a39b70d;
47                uint64_t m1 = (tmp >> 64) ^ tmp;
48                tmp = (__uint128_t)m1 * 0x1b03738712fad5c9;
49                uint64_t m2 = (tmp >> 64) ^ tmp;
50                return m2;
51        }
52#endif
53
54//--------------------------------------------------
55static inline uint64_t xorshift_13_7_17( uint64_t & state ) {
56        uint64_t ret = state;
57        state ^= state << 13;
58        state ^= state >> 7;
59        state ^= state << 17;
60        return ret;
61}
62
63//--------------------------------------------------
64
65#ifdef XORSHIFT_6_21_7
66#define PRNG_ARG_T uint32_t
67#define PRNG_NAME xorshift_6_21_7
68#endif // XORSHIFT_6_21_7
69
70static inline uint32_t xorshift_6_21_7( uint32_t & state ) {
71        uint32_t ret = state;
72        state ^= state << 6;
73        state ^= state >> 21;
74        state ^= state << 7;
75        return ret;
76} // xorshift_6_21_7
77
78//--------------------------------------------------
79typedef struct {
80  uint32_t a, b, c, d;
81  uint32_t counter;
82} xorwow__state_t;
83
84// The state array must be initialized to not be all zero in the first four words.
85static inline uint32_t xorwow( xorwow__state_t & state ) {
86        // Algorithm "xorwow" from p. 5 of Marsaglia, "Xorshift RNGs".
87        uint32_t ret = state.a + state.counter;
88        uint32_t t = state.d;
89
90        uint32_t const s = state.a;
91        state.d = state.c;
92        state.c = state.b;
93        state.b = s;
94
95        t ^= t >> 2;
96        t ^= t << 1;
97        t ^= s ^ (s << 4);
98        state.a = t;
99
100        state.counter += 362437;
101        return ret;
102}
103
104//--------------------------------------------------
105static inline uint32_t LCG( uint32_t & state ) {                // linear congruential generator
106        uint32_t ret = state;
107        state = 36969 * (state & 65535) + (state >> 16);        // 36969 is NOT prime! No not change it!
108        return ret;
109} // LCG
110
111//--------------------------------------------------
112#define M  (1_l64u << 48_l64u)
113#define A  (25214903917_l64u)
114#define AI (18446708753438544741_l64u)
115#define C  (11_l64u)
116#define D  (16_l64u)
117
118// Bi-directional LCG random-number generator
119static inline uint32_t LCGBI_fwd( uint64_t & state ) {
120        state = (A * state + C) & (M - 1);
121        return state >> D;
122}
123
124static inline uint32_t LCGBI_bck( uint64_t & state ) {
125        unsigned int r = state >> D;
126        state = AI * (state - C) & (M - 1);
127        return r;
128}
129
130#undef M
131#undef A
132#undef AI
133#undef C
134#undef D
Note: See TracBrowser for help on using the repository browser.