GeNN  4.9.0
GPU enhanced Neuronal Networks (GeNN)
lfsr113.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_LFSR113_CH
39 #define PRIVATE_LFSR113_CH
40 
41 #define Lfsr113_NORM_cl_double 1.0 / 0x100000001L // 2^32 + 1 // 2.328306436538696e-10
42 #define Lfsr113_NORM_cl_float 2.3283063e-10f
43 
44 
45 clrngStatus clrngLfsr113CopyOverStreams(size_t count, clrngLfsr113Stream* destStreams, const clrngLfsr113Stream* srcStreams)
46 {
47  //Check params
48  if (!destStreams)
49  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): destStreams cannot be NULL", __func__);
50  if (!srcStreams)
51  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): srcStreams cannot be NULL", __func__);
52 
53  for (size_t i = 0; i < count; i++)
54  destStreams[i] = srcStreams[i];
55 
56  return CLRNG_SUCCESS;
57 }
58 
61 static cl_ulong clrngLfsr113NextState(clrngLfsr113StreamState *currentState) {
62 
63  cl_ulong b;
64 
65  b = (((currentState->g[0] << 6) ^ currentState->g[0]) >> 13);
66  currentState->g[0] = (((currentState->g[0] & 4294967294U) << 18) ^ b);
67 
68  b = (((currentState->g[1] << 2) ^ currentState->g[1]) >> 27);
69  currentState->g[1] = (((currentState->g[1] & 4294967288U) << 2) ^ b);
70 
71  b = (((currentState->g[2] << 13) ^ currentState->g[2]) >> 21);
72  currentState->g[2] = (((currentState->g[2] & 4294967280U) << 7) ^ b);
73 
74  b = (((currentState->g[3] << 3) ^ currentState->g[3]) >> 12);
75  currentState->g[3] = (((currentState->g[3] & 4294967168U) << 13) ^ b);
76 
77  return (currentState->g[0] ^ currentState->g[1] ^ currentState->g[2] ^ currentState->g[3]);
78 
79 }
80 
81 // The following would be much cleaner with C++ templates instead of macros.
82 
83 // We use an underscore on the r.h.s. to avoid potential recursion with certain
84 // preprocessors.
85 #define IMPLEMENT_GENERATE_FOR_TYPE(fptype) \
86  \
87  fptype clrngLfsr113RandomU01_##fptype(clrngLfsr113Stream* stream) { \
88  return clrngLfsr113NextState(&stream->current) * Lfsr113_NORM_##fptype; \
89  } \
90  \
91  cl_int clrngLfsr113RandomInteger_##fptype(clrngLfsr113Stream* stream, cl_int i, cl_int j) { \
92  return i + (cl_int)((j - i + 1) * clrngLfsr113RandomU01_##fptype(stream)); \
93  } \
94  \
95  clrngStatus clrngLfsr113RandomU01Array_##fptype(clrngLfsr113Stream* stream, size_t count, fptype* buffer) { \
96  if (!stream) \
97  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): stream cannot be NULL", __func__); \
98  if (!buffer) \
99  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): buffer cannot be NULL", __func__); \
100  for (size_t i = 0; i < count; i++) \
101  buffer[i] = clrngLfsr113RandomU01_##fptype(stream); \
102  return CLRNG_SUCCESS; \
103  } \
104  \
105  clrngStatus clrngLfsr113RandomIntegerArray_##fptype(clrngLfsr113Stream* stream, cl_int i, cl_int j, size_t count, cl_int* buffer) { \
106  if (!stream) \
107  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): stream cannot be NULL", __func__); \
108  if (!buffer) \
109  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): buffer cannot be NULL", __func__); \
110  for (size_t k = 0; k < count; k++) \
111  buffer[k] = clrngLfsr113RandomInteger_##fptype(stream, i, j); \
112  return CLRNG_SUCCESS; \
113  }
114 
115 // On the host, implement everything.
116 // On the device, implement only what is required to avoid cluttering memory.
117 #if defined(CLRNG_SINGLE_PRECISION) || !defined(__CLRNG_DEVICE_API)
119 #endif
120 #if !defined(CLRNG_SINGLE_PRECISION) || !defined(__CLRNG_DEVICE_API)
122 #endif
123 
124 // Clean up macros, especially to avoid polluting device code.
125 #undef IMPLEMENT_GENERATE_FOR_TYPE
126 
127 
128 
130 {
131  //Check params
132  if (!streams)
133  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): streams cannot be NULL", __func__);
134  //Reset current state to the stream initial state
135  for (size_t j = 0; j < count; j++) {
136 #ifdef __CLRNG_DEVICE_API
137 #ifdef CLRNG_ENABLE_SUBSTREAMS
138  streams[j].current = streams[j].substream = *streams[j].initial;
139 #else
140  streams[j].current = *streams[j].initial;
141 #endif
142 #else
143  streams[j].current = streams[j].substream = streams[j].initial;
144 #endif
145  }
146 
147  return CLRNG_SUCCESS;
148 }
149 
150 #if defined(CLRNG_ENABLE_SUBSTREAMS) || !defined(__CLRNG_DEVICE_API)
152 {
153  //Check params
154  if (!streams)
155  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): streams cannot be NULL", __func__);
156  //Reset current state to the subStream initial state
157  for (size_t j = 0; j < count; j++) {
158  streams[j].current = streams[j].substream;
159  }
160 
161  return CLRNG_SUCCESS;
162 }
164 
165  /* The following operations make the jump ahead with
166  2 ^ 55 iterations for every component of the generator.
167  The internal state after the jump, however, is slightly different
168  from 2 ^ 55 iterations since it ignores the state in
169  which are found the first bits of each components,
170  since they are ignored in the recurrence.The state becomes
171  identical to what one would with normal iterations
172  after a call nextValue().*/
173 
174  int z, b;
175 
176  cl_uint* subStreamState = stream->substream.g;
177 
178  //Calculate the first component
179  z = subStreamState[0] & (cl_uint)-2;
180  b = (z << 6) ^ z;
181 
182  z = (z) ^ (z << 3) ^ (z << 4) ^ (z << 6) ^ (z << 7) ^
183  (z << 8) ^ (z << 10) ^ (z << 11) ^ (z << 13) ^ (z << 14) ^
184  (z << 16) ^ (z << 17) ^ (z << 18) ^ (z << 22) ^
185  (z << 24) ^ (z << 25) ^ (z << 26) ^ (z << 28) ^ (z << 30);
186 
187  z ^= ((b >> 1) & 0x7FFFFFFF) ^
188  ((b >> 3) & 0x1FFFFFFF) ^
189  ((b >> 5) & 0x07FFFFFF) ^
190  ((b >> 6) & 0x03FFFFFF) ^
191  ((b >> 7) & 0x01FFFFFF) ^
192  ((b >> 9) & 0x007FFFFF) ^
193  ((b >> 13) & 0x0007FFFF) ^
194  ((b >> 14) & 0x0003FFFF) ^
195  ((b >> 15) & 0x0001FFFF) ^
196  ((b >> 17) & 0x00007FFF) ^
197  ((b >> 18) & 0x00003FFF) ^
198  ((b >> 20) & 0x00000FFF) ^
199  ((b >> 21) & 0x000007FF) ^
200  ((b >> 23) & 0x000001FF) ^
201  ((b >> 24) & 0x000000FF) ^
202  ((b >> 25) & 0x0000007F) ^
203  ((b >> 26) & 0x0000003F) ^
204  ((b >> 27) & 0x0000001F) ^
205  ((b >> 30) & 0x00000003);
206  subStreamState[0] = z;
207 
208  //Calculate the second component
209  z = subStreamState[1] & (cl_uint)-8;
210  b = z ^ (z << 1);
211  b ^= (b << 2);
212  b ^= (b << 4);
213  b ^= (b << 8);
214 
215  b <<= 8;
216  b ^= (z << 22) ^ (z << 25) ^ (z << 27);
217  if ((z & 0x80000000) != 0) b ^= 0xABFFF000;
218  if ((z & 0x40000000) != 0) b ^= 0x55FFF800;
219 
220  z = b ^ ((z >> 7) & 0x01FFFFFF) ^
221  ((z >> 20) & 0x00000FFF) ^
222  ((z >> 21) & 0x000007FF);
223 
224  subStreamState[1] = z;
225 
226  //Calculate the third component
227  z = subStreamState[2] & (cl_uint)-16;
228  b = (z << 13) ^ z;
229  z = ((b >> 3) & 0x1FFFFFFF) ^
230  ((b >> 17) & 0x00007FFF) ^
231  (z << 10) ^ (z << 11) ^ (z << 25);
232  subStreamState[2] = z;
233 
234  //Calculate the forth component
235  z = subStreamState[3] & (cl_uint)-128;
236  b = (z << 3) ^ z;
237  z = (z << 14) ^ (z << 16) ^ (z << 20) ^
238  ((b >> 5) & 0x07FFFFFF) ^
239  ((b >> 9) & 0x007FFFFF) ^
240  ((b >> 11) & 0x001FFFFF);
241  subStreamState[3] = z;
242 
243  clrngLfsr113RewindSubstreams(1, stream);
244 }
246 {
247  //Check params
248  if (!streams)
249  return clrngSetErrorString(CLRNG_INVALID_VALUE, "%s(): streams cannot be NULL", __func__);
250 
251  for (size_t k = 0; k < count; k++) {
252 
253  lfsr113ResetNextSubStream(&streams[k]);
254  }
255 
256  return CLRNG_SUCCESS;
257 }
258 
260 {
261  for (size_t i = 0; i < count; i++) {
262  clrngStatus err;
263  // snapshot current stream into substreams[i]
264  err = clrngLfsr113CopyOverStreams(1, &substreams[i], stream);
265  if (err != CLRNG_SUCCESS)
266  return err;
267  // advance to next substream
268  err = clrngLfsr113ForwardToNextSubstreams(1, stream);
269  if (err != CLRNG_SUCCESS)
270  return err;
271  }
272  return CLRNG_SUCCESS;
273 }
274 
275 #endif
276 
277 #endif // PRIVATE_Lfsr113_CH
clrngStatus clrngLfsr113CopyOverStreams(size_t count, clrngLfsr113Stream *destStreams, const clrngLfsr113Stream *srcStreams)
Definition: lfsr113.c.h:45
enum clrngStatus_ clrngStatus
Error codes.
Definition: lfsr113.h:59
Definition: clRNG.h:343
Definition: lfsr113.h:52
void lfsr113ResetNextSubStream(clrngLfsr113Stream *stream)
Definition: lfsr113.c.h:163
clrngStatus clrngLfsr113RewindStreams(size_t count, clrngLfsr113Stream *streams)
Definition: lfsr113.c.h:129
clrngStatus clrngSetErrorString(cl_int err, const char *msg,...)
Set the current error string.
Definition: private.c:57
clrngLfsr113StreamState initial
Definition: lfsr113.h:66
clrngStatus clrngLfsr113ForwardToNextSubstreams(size_t count, clrngLfsr113Stream *streams)
Definition: lfsr113.c.h:245
clrngStatus clrngLfsr113MakeOverSubstreams(clrngLfsr113Stream *stream, size_t count, clrngLfsr113Stream *substreams)
Definition: lfsr113.c.h:259
Definition: clRNG.h:345
cl_uint g[4]
Seed for the first LFSR component.
Definition: lfsr113.h:55
clrngLfsr113StreamState substream
Definition: lfsr113.h:67
#define IMPLEMENT_GENERATE_FOR_TYPE(fptype)
Definition: lfsr113.c.h:85
clrngStatus clrngLfsr113RewindSubstreams(size_t count, clrngLfsr113Stream *streams)
Definition: lfsr113.c.h:151
clrngLfsr113StreamState current
Definition: lfsr113.h:65