MCKL
Monte Carlo Kernel Library
philox.h
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/randomc/philox.h
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_RANDOMC_PHILOX_H
33 #define MCKL_RANDOMC_PHILOX_H
34 
35 #include <mckl/internal/config.h>
36 
37 #ifndef UINT32_C
38 #error __STDC_CONSTANT_MACROS not defined before #include<stdint.h>
39 #endif
40 
43 typedef struct {
44  uint32_t v[2];
46 
49 typedef struct {
50  uint32_t v[4];
52 
55 typedef struct {
56  uint32_t v[1];
58 
61 typedef struct {
62  uint32_t v[2];
64 
65 typedef struct {
66  uint32_t v[1];
68 
69 typedef struct {
70  uint32_t v[2];
72 
75 typedef struct {
81 
84 typedef struct {
90 
92 {
93  if (++ctr->v[0] != 0) {
94  return;
95  }
96  if (++ctr->v[1] != 0) {
97  return;
98  }
99 }
100 
102 {
103  if (++ctr->v[0] != 0) {
104  return;
105  }
106  if (++ctr->v[1] != 0) {
107  return;
108  }
109  if (++ctr->v[2] != 0) {
110  return;
111  }
112  if (++ctr->v[3] != 0) {
113  return;
114  }
115 }
116 
117 static inline void mckl_philox2x32_initpar(
119 {
120  par->v[0] = key->v[0];
121 }
122 
123 static inline void mckl_philox4x32_initpar(
125 {
126  par->v[0] = key->v[0];
127  par->v[1] = key->v[1];
128 }
129 
131 {
132  par->v[0] += UINT32_C(0x9E3779B9);
133 }
134 
136 {
137  par->v[0] += UINT32_C(0x9E3779B9);
138  par->v[1] += UINT32_C(0xBB67AE85);
139 }
140 
141 static inline void mckl_philox2x32_round(
142  mckl_philox2x32_ctr_t *state, const mckl_philox2x32_par_t *par)
143 {
144 #ifdef __cplusplus
145  uint64_t p = static_cast<uint64_t>(state->v[0]) * UINT64_C(0xD256D193);
146  uint32_t hi = static_cast<uint32_t>(p >> 32);
147  uint32_t lo = static_cast<uint32_t>(p);
148 #else
149  uint64_t p = ((uint64_t)(state->v[0])) * UINT64_C(0xD256D193);
150  uint32_t hi = (uint32_t)(p >> 32);
151  uint32_t lo = (uint32_t)(p);
152 #endif
153  hi ^= par->v[0];
154  state->v[0] = hi ^ (state->v[1]);
155  state->v[1] = lo;
156 }
157 
158 static inline void mckl_philox4x32_round(
159  mckl_philox4x32_ctr_t *state, const mckl_philox4x32_par_t *par)
160 {
161 #ifdef __cplusplus
162  uint64_t p0 = static_cast<uint64_t>(state->v[0]) * UINT64_C(0xD2511F53);
163  uint64_t p2 = static_cast<uint64_t>(state->v[2]) * UINT64_C(0xCD9E8D57);
164  uint32_t hi0 = static_cast<uint32_t>(p2 >> 32);
165  uint32_t lo1 = static_cast<uint32_t>(p2);
166  uint32_t hi2 = static_cast<uint32_t>(p0 >> 32);
167  uint32_t lo3 = static_cast<uint32_t>(p0);
168 #else
169  uint64_t p0 = ((uint64_t)(state->v[0])) * UINT64_C(0xD2511F53);
170  uint64_t p2 = ((uint64_t)(state->v[2])) * UINT64_C(0xCD9E8D57);
171  uint32_t hi0 = (uint32_t)(p2 >> 32);
172  uint32_t lo1 = (uint32_t)(p2);
173  uint32_t hi2 = (uint32_t)(p0 >> 32);
174  uint32_t lo3 = (uint32_t)(p0);
175 #endif
176  hi0 ^= par->v[0];
177  hi2 ^= par->v[1];
178  state->v[0] = hi0 ^ (state->v[1]);
179  state->v[1] = lo1;
180  state->v[2] = hi2 ^ (state->v[3]);
181  state->v[3] = lo3;
182 }
183 
186 static inline void mckl_philox2x32_gen(const mckl_philox2x32_ctr_t *ctr,
187  const mckl_philox2x32_key_t *key, mckl_philox2x32_ctr_t *state)
188 {
189  *state = *ctr;
191  mckl_philox2x32_initpar(key, &par);
192 
193  mckl_philox2x32_round(state, &par);
195  mckl_philox2x32_round(state, &par);
197  mckl_philox2x32_round(state, &par);
199  mckl_philox2x32_round(state, &par);
201  mckl_philox2x32_round(state, &par);
203  mckl_philox2x32_round(state, &par);
205  mckl_philox2x32_round(state, &par);
207  mckl_philox2x32_round(state, &par);
209  mckl_philox2x32_round(state, &par);
211  mckl_philox2x32_round(state, &par);
212 }
213 
216 static inline void mckl_philox4x32_gen(const mckl_philox4x32_ctr_t *ctr,
217  const mckl_philox4x32_key_t *key, mckl_philox4x32_ctr_t *state)
218 {
219  *state = *ctr;
221  mckl_philox4x32_initpar(key, &par);
222 
223  mckl_philox4x32_round(state, &par);
225  mckl_philox4x32_round(state, &par);
227  mckl_philox4x32_round(state, &par);
229  mckl_philox4x32_round(state, &par);
231  mckl_philox4x32_round(state, &par);
233  mckl_philox4x32_round(state, &par);
235  mckl_philox4x32_round(state, &par);
237  mckl_philox4x32_round(state, &par);
239  mckl_philox4x32_round(state, &par);
241  mckl_philox4x32_round(state, &par);
242 }
243 
246 static inline void mckl_philox2x32_init(mckl_philox2x32 *rng, uint32_t seed)
247 {
248  rng->ctr.v[0] = 0;
249  rng->ctr.v[1] = 0;
250  rng->key.v[0] = seed;
251  rng->index = 2;
252 }
253 
256 static inline void mckl_philox4x32_init(mckl_philox4x32 *rng, uint32_t seed)
257 {
258  rng->ctr.v[0] = 0;
259  rng->ctr.v[1] = 0;
260  rng->ctr.v[2] = 0;
261  rng->ctr.v[3] = 0;
262  rng->key.v[0] = seed;
263  rng->key.v[1] = 0;
264  rng->index = 4;
265 }
266 
270 {
271  if (rng->index == 2) {
272  mckl_philox2x32_inc(&rng->ctr);
273  mckl_philox2x32_gen(&rng->ctr, &rng->key, &rng->state);
274  rng->index = 0;
275  }
276 
277  return rng->state.v[rng->index++];
278 }
279 
283 {
284  if (rng->index == 4) {
285  mckl_philox4x32_inc(&rng->ctr);
286  mckl_philox4x32_gen(&rng->ctr, &rng->key, &rng->state);
287  rng->index = 0;
288  }
289 
290  return rng->state.v[rng->index++];
291 }
292 
293 #endif // MCKL_RANDOMC_PHILOX_H
#define UINT64_C(x)
Definition: opencl.h:44
uint32_t index
Definition: philox.h:88
static uint32_t mckl_philox2x32_rand(mckl_philox2x32 *rng)
Generate random 32-bit integers from Philox2x32 RNG.
Definition: philox.h:269
Philox2x32 counter type.
Definition: philox.h:43
Philox4x32 key type.
Definition: philox.h:61
static void mckl_philox4x32_inc(mckl_philox4x32_ctr_t *ctr)
Definition: philox.h:101
Philox4x32 counter type.
Definition: philox.h:49
Philox2x32 key type.
Definition: philox.h:55
uint uint32_t
Definition: opencl.h:41
ulong uint64_t
Definition: opencl.h:42
static uint32_t mckl_philox4x32_rand(mckl_philox4x32 *rng)
Generate random 32-bit integers from Philox4x32 RNG.
Definition: philox.h:282
static void mckl_philox2x32_initpar(const mckl_philox2x32_key_t *key, mckl_philox2x32_par_t *par)
Definition: philox.h:117
static void mckl_philox2x32_init(mckl_philox2x32 *rng, uint32_t seed)
Initialize Philox2x32 RNG state.
Definition: philox.h:246
mckl_philox4x32_ctr_t ctr
Definition: philox.h:86
mckl_philox4x32_key_t key
Definition: philox.h:87
uint32_t v[4]
Definition: philox.h:50
static void mckl_philox2x32_gen(const mckl_philox2x32_ctr_t *ctr, const mckl_philox2x32_key_t *key, mckl_philox2x32_ctr_t *state)
Generate Philox2x32 RNG state.
Definition: philox.h:186
Philox2x32 RNG state structure.
Definition: philox.h:75
uint32_t index
Definition: philox.h:79
static void mckl_philox4x32_initpar(const mckl_philox4x32_key_t *key, mckl_philox4x32_par_t *par)
Definition: philox.h:123
Philox4x32 RNG state structure.
Definition: philox.h:84
static void mckl_philox4x32_bumpkey(mckl_philox4x32_par_t *par)
Definition: philox.h:135
uint32_t v[2]
Definition: philox.h:44
mckl_philox2x32_key_t key
Definition: philox.h:78
mckl_philox2x32_ctr_t state
Definition: philox.h:76
static void mckl_philox2x32_bumpkey(mckl_philox2x32_par_t *par)
Definition: philox.h:130
uint32_t v[1]
Definition: philox.h:66
static void mckl_philox4x32_init(mckl_philox4x32 *rng, uint32_t seed)
Initialize Philox4x32 RNG state.
Definition: philox.h:256
static void mckl_philox4x32_gen(const mckl_philox4x32_ctr_t *ctr, const mckl_philox4x32_key_t *key, mckl_philox4x32_ctr_t *state)
Generate Philox4x32 RNG state.
Definition: philox.h:216
mckl_philox4x32_ctr_t state
Definition: philox.h:85
#define UINT32_C(x)
Definition: opencl.h:43
uint32_t v[2]
Definition: philox.h:62
uint32_t v[1]
Definition: philox.h:56
static void mckl_philox2x32_round(mckl_philox2x32_ctr_t *state, const mckl_philox2x32_par_t *par)
Definition: philox.h:141
static void mckl_philox4x32_round(mckl_philox4x32_ctr_t *state, const mckl_philox4x32_par_t *par)
Definition: philox.h:158
mckl_philox2x32_ctr_t ctr
Definition: philox.h:77
uint32_t v[2]
Definition: philox.h:70
static void mckl_philox2x32_inc(mckl_philox2x32_ctr_t *ctr)
Definition: philox.h:91