GeNN  4.9.0
GPU enhanced Neuronal Networks (GeNN)
philox432.c.h
Go to the documentation of this file.
1 
2  /*
3  ***********************************************************************
4  Copyright (c) 2015 Advanced Micro Devices, Inc.
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without
8  modification, are permitted provided that the following conditions
9  are met:
10 
11  1. Redistributions of source code must retain the above copyright
12  notice, this list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright
15  notice, this list of conditions and the following disclaimer in the
16  documentation and/or other materials provided with the distribution.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30  ***********************************************************************
31  */
32 
37 #pragma once
38 #ifndef PRIVATE_PHILOX432_CH
39 #define PRIVATE_PHILOX432_CH
40 
41 #include "Random123/philox.h"
42 
43 #define Philox432_NORM_cl_double 1.0 / 0x100000000L // 1.0 /2^32
44 #define Philox432_NORM_cl_float 2.32830644e-010f;
45 
47 {
49 
50  c.L.lsb = a.L.lsb + b.L.lsb;
51  c.L.msb = a.L.msb + b.L.msb + (c.L.lsb < a.L.lsb);
52 
53  c.H.lsb = a.H.lsb + b.H.lsb + (c.L.msb < a.L.msb);
54  c.H.msb = a.H.msb + b.H.msb + (c.H.lsb < a.H.lsb);
55 
56  return c;
57 }
58 
60 {
62 
63  c.L.lsb = a.L.lsb - b.L.lsb;
64  c.L.msb = a.L.msb - b.L.msb - (c.L.lsb > a.L.lsb);
65 
66  c.H.lsb = a.H.lsb - b.H.lsb - (c.L.msb > a.L.msb);
67  c.H.msb = a.H.msb - b.H.msb - (c.H.lsb > a.H.lsb);
68 
69  return c;
70 }
71 
73 {
74  //Check params
75  if (!destStreams)
76  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): destStreams cannot be NULL", __func__);
77  if (!srcStreams)
78  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): srcStreams cannot be NULL", __func__);
79 
80  for (size_t i = 0; i < count; i++)
81  destStreams[i] = srcStreams[i];
82 
83  return CLRNG_SUCCESS;
84 }
85 
87 {
88  //Default key
89  philox4x32_key_t k = { { currentState->key[0], currentState->key[1] } };
90 
91  //get the currect state
92  philox4x32_ctr_t c = { { 0 } };
93  c.v[0] = currentState->ctr.L.lsb;
94  c.v[1] = currentState->ctr.L.msb;
95  c.v[2] = currentState->ctr.H.lsb;
96  c.v[3] = currentState->ctr.H.msb;
97 
98  //Generate 4 uint and store them into the stream state
99  philox4x32_ctr_t r = philox4x32(c, k);
100  currentState->deck[3] = r.v[0];
101  currentState->deck[2] = r.v[1];
102  currentState->deck[1] = r.v[2];
103  currentState->deck[0] = r.v[3];
104 }
105 
108 static cl_uint clrngPhilox432NextState(clrngPhilox432StreamState *currentState) {
109 
110  if (currentState->deckIndex == 0)
111  {
112  clrngPhilox432GenerateDeck(currentState);
113 
114  }
115 
116  cl_uint result = currentState->deck[currentState->deckIndex];
117 
118  currentState->deckIndex++;
119 
120  // Advance to the next Counter.
121  if (currentState->deckIndex == 4) {
122 
123  clrngPhilox432Counter incBy1 = { { 0, 0 }, { 0, 1 } };
124  currentState->ctr = clrngPhilox432Add(currentState->ctr, incBy1);
125 
126  currentState->deckIndex = 0;
127  clrngPhilox432GenerateDeck(currentState);
128  }
129 
130  return result;
131 
132 }
133 // The following would be much cleaner with C++ templates instead of macros.
134 
135 // We use an underscore on the r.h.s. to avoid potential recursion with certain
136 // preprocessors.
137 #define IMPLEMENT_GENERATE_FOR_TYPE(fptype) \
138  \
139  fptype clrngPhilox432RandomU01_##fptype(clrngPhilox432Stream* stream) { \
140  return (clrngPhilox432NextState(&stream->current) + 0.5) * Philox432_NORM_##fptype; \
141  } \
142  \
143  cl_int clrngPhilox432RandomInteger_##fptype(clrngPhilox432Stream* stream, cl_int i, cl_int j) { \
144  return i + (cl_int)((j - i + 1) * clrngPhilox432RandomU01_##fptype(stream)); \
145  } \
146  \
147  clrngStatus clrngPhilox432RandomU01Array_##fptype(clrngPhilox432Stream* stream, size_t count, fptype* buffer) { \
148  if (!stream) \
149  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): stream cannot be NULL", __func__); \
150  if (!buffer) \
151  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): buffer cannot be NULL", __func__); \
152  for (size_t i = 0; i < count; i++) \
153  buffer[i] = clrngPhilox432RandomU01_##fptype(stream); \
154  return CLRNG_SUCCESS; \
155  } \
156  \
157  clrngStatus clrngPhilox432RandomIntegerArray_##fptype(clrngPhilox432Stream* stream, cl_int i, cl_int j, size_t count, cl_int* buffer) { \
158  if (!stream) \
159  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): stream cannot be NULL", __func__); \
160  if (!buffer) \
161  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): buffer cannot be NULL", __func__); \
162  for (size_t k = 0; k < count; k++) \
163  buffer[k] = clrngPhilox432RandomInteger_##fptype(stream, i, j); \
164  return CLRNG_SUCCESS; \
165  }
166 
167 // On the host, implement everything.
168 // On the device, implement only what is required to avoid cluttering memory.
169 #if defined(CLRNG_SINGLE_PRECISION) || !defined(__CLRNG_DEVICE_API)
171 #endif
172 #if !defined(CLRNG_SINGLE_PRECISION) || !defined(__CLRNG_DEVICE_API)
174 #endif
175 
176 // Clean up macros, especially to avoid polluting device code.
177 #undef IMPLEMENT_GENERATE_FOR_TYPE
178 
179 
180 
182 {
183  //Check params
184  if (!streams)
185  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): streams cannot be NULL", __func__);
186  //Reset current state to the stream initial state
187  for (size_t j = 0; j < count; j++) {
188 #ifdef __CLRNG_DEVICE_API
189 #ifdef CLRNG_ENABLE_SUBSTREAMS
190  streams[j].current = streams[j].substream = *streams[j].initial;
191 #else
192  streams[j].current = *streams[j].initial;
193 #endif
194 #else
195  streams[j].current = streams[j].substream = streams[j].initial;
196 #endif
197 }
198 
199  return CLRNG_SUCCESS;
200 }
201 
202 #if defined(CLRNG_ENABLE_SUBSTREAMS) || !defined(__CLRNG_DEVICE_API)
203 
205 {
206  //Check params
207  if (!streams)
208  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): streams cannot be NULL", __func__);
209  //Reset current state to the subStream initial state
210  for (size_t j = 0; j < count; j++) {
211  streams[j].current = streams[j].substream;
212  }
213 
214  return CLRNG_SUCCESS;
215 }
216 
218 
219  //2^64 states
220  clrngPhilox432Counter steps = { { 0, 1 }, { 0, 0 } };
221 
222  //move the substream counter 2^64 steps forward.
223  stream->substream.ctr = clrngPhilox432Add(stream->substream.ctr, steps);
224 
226 }
227 
229 {
230  //Check params
231  if (!streams)
232  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): streams cannot be NULL", __func__);
233 
234  for (size_t k = 0; k < count; k++) {
235 
236  Philox432ResetNextSubStream(&streams[k]);
237  }
238 
239  return CLRNG_SUCCESS;
240 }
241 
243 {
244  for (size_t i = 0; i < count; i++) {
245  clrngStatus err;
246  // snapshot current stream into substreams[i]
247  err = clrngPhilox432CopyOverStreams(1, &substreams[i], stream);
248  if (err != CLRNG_SUCCESS)
249  return err;
250  // advance to next substream
251  err = clrngPhilox432ForwardToNextSubstreams(1, stream);
252  if (err != CLRNG_SUCCESS)
253  return err;
254  }
255  return CLRNG_SUCCESS;
256 }
257 
258 #endif
259 
260 #endif // PRIVATE_Philox432_CH
void clrngPhilox432GenerateDeck(clrngPhilox432StreamState *currentState)
Definition: philox432.c.h:86
clrngPhilox432Counter ctr
Definition: philox432.h:64
clrngPhilox432Counter clrngPhilox432Add(clrngPhilox432Counter a, clrngPhilox432Counter b)
Definition: philox432.c.h:46
#define philox4x32(c, k)
Definition: philox.h:352
clrngPhilox432StreamState initial
Definition: philox432.h:77
clrngPhilox432SB L
Definition: philox432.h:58
cl_uint key[2]
Definition: philox432.h:63
#define IMPLEMENT_GENERATE_FOR_TYPE(fptype)
Definition: philox432.c.h:137
enum clrngStatus_ clrngStatus
Error codes.
Definition: philox432.h:57
cl_uint lsb
Definition: philox432.h:54
clrngPhilox432SB H
Definition: philox432.h:58
Definition: clRNG.h:343
void Philox432ResetNextSubStream(clrngPhilox432Stream *stream)
Definition: philox432.c.h:217
clrngStatus clrngPhilox432CopyOverStreams(size_t count, clrngPhilox432Stream *destStreams, const clrngPhilox432Stream *srcStreams)
Definition: philox432.c.h:72
clrngStatus clrngSetErrorString(cl_int err, const char *msg,...)
Set the current error string.
Definition: private.c:57
clrngStatus clrngPhilox432RewindSubstreams(size_t count, clrngPhilox432Stream *streams)
Definition: philox432.c.h:204
clrngStatus clrngPhilox432ForwardToNextSubstreams(size_t count, clrngPhilox432Stream *streams)
Definition: philox432.c.h:228
clrngPhilox432StreamState current
Definition: philox432.h:76
cl_uint msb
Definition: philox432.h:54
clrngPhilox432Counter clrngPhilox432Substract(clrngPhilox432Counter a, clrngPhilox432Counter b)
Definition: philox432.c.h:59
Definition: clRNG.h:345
clrngPhilox432StreamState substream
Definition: philox432.h:78
cl_uint deck[4]
Definition: philox432.h:65
clrngStatus clrngPhilox432MakeOverSubstreams(clrngPhilox432Stream *stream, size_t count, clrngPhilox432Stream *substreams)
Definition: philox432.c.h:242
Definition: philox432.h:62
cl_uint deckIndex
Definition: philox432.h:66
clrngStatus clrngPhilox432RewindStreams(size_t count, clrngPhilox432Stream *streams)
Definition: philox432.c.h:181
Definition: philox432.h:70