GPU Workshop Sample Code
 All Data Structures Namespaces Files Functions Variables Macros Pages
rng.c
Go to the documentation of this file.
1 
6 #include <math.h>
7 const float TWOPI = 6.283185307179586;
8 
9 
10 
21 __device__
22 unsigned int TausStep( unsigned int * seed,
23  int S1,
24  int S2,
25  int S3,
26  unsigned int M )
27 {
28  unsigned int b=(((*seed << S1) ^ *seed) >> S2);
29  return *seed = (((*seed & M) << S3) ^ b);
30 }
31 
32 
40 __device__
41 unsigned int LCGStep( unsigned int * seed,
42  unsigned int A,
43  unsigned int C )
44 {
45  return *seed = ( A * *seed + C );
46 }
47 
48 
49 
58 __device__
59 float hybrid_tausworth_rng( unsigned int * seed1,
60  unsigned int * seed2,
61  unsigned int * seed3,
62  unsigned int * seed4 )
63 { // Periods
64  unsigned int u =
65  TausStep( seed1, 13, 19, 12, 4294967294UL ) // p1=2^31-1
66  ^ TausStep( seed2, 2, 25, 4, 4294967288UL ) // p2=2^30-1
67  ^ TausStep( seed3, 3, 11, 17, 4294967280UL ) // p3=2^28-1
68  ^ LCGStep( seed4, 1664525, 1013904223UL); // p4=2^32
69  return u*2.3283064365387e-10;
70 }
71 
72 
73 
74 
87 __device__ __host__
88 unsigned int mult_with_carry_rng( unsigned int * seed1,
89  unsigned int * seed2 )
90 {
91  *seed1 = 36969u * ( *seed1 & 65535u ) + ( *seed1 >> 16 );
92  *seed2 = 18000u * ( *seed2 & 65535u ) + ( *seed2 >> 16 );
93  return (( *seed1 << 16 ) + *seed2 );
94 }
95 
96 
97 
109 void initialize_rng_seeds( unsigned int * seeds,
110  unsigned int * meta_seed,
111  int n )
112 {
113  unsigned int seed1 = meta_seed[0];
114  unsigned int seed2 = meta_seed[1];
115  for (int i=0;i<n*4;i++){
116  do {
117  seeds[i] = mult_with_carry_rng( &seed1, &seed2 );
118  } while (seeds[i]<128); // seeds should be greater than 128 for Tausworth generator.
119  }
120  meta_seed[0] = seed1;
121  meta_seed[1] = seed2;
122 }
123 
124 
125 
126 __device__
127 void get_seed( unsigned int * seed,
128  unsigned int * rng_state,
129  int i,
130  int n )
131 {
132  for (int k=0;k<4;k++)
133  seed[k] = rng_state[k*n+i];
134 }
135 
136 
137 
138 __device__
139 void put_seed( unsigned int * seed,
140  unsigned int * rng_state,
141  int i,
142  int n )
143 {
144  for (int k=0;k<4;k++)
145  rng_state[k*n+i] = seed[k];
146 }
147 
148 
149 
150 
151 __device__
152 float random_uniform( unsigned int * seed )
153 {
154  return hybrid_tausworth_rng( &seed[0], &seed[1], &seed[2], &seed[3] );
155 }
156 
157 
158 
159 
160 __device__
161 float random_uniform_positive( unsigned int * seed )
162 {
163  float u=-1.0;
164  do {
165  u = random_uniform( seed );
166  } while (u<=0);
167  return u;
168 }
169 
170 
171 
180 template <typename T>
181 __device__
182 void random_normal( T * z1,
183  T * z2,
184  unsigned int * seed )
185 {
186  T u0 = random_uniform_positive( seed );
187  T u1 = random_uniform( seed );
188  T r = sqrt( -2.0 * log( u0 ));
189  T theta = TWOPI*u1;
190  *z1 = r * sin( theta );
191  *z2 = r * cos( theta );
192 }
193