vnl_random.cxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_random.cxx
2 //:
3 // \file
4 
5 #include <ctime>
6 #include <cmath>
7 #include "vnl_random.h"
8 #include <cassert>
9 
11 {
13 }
14 
15 //: Construct with seed
16 vnl_random::vnl_random(unsigned long seed)
17  : linear_congruential_previous(seed), mz_array_position(0UL), mz_borrow(0), mz_previous_normal_flag(0)
18 {reseed(seed);}
19 
20 //: Construct with seed
22  : mz_array_position(0UL), mz_borrow(0), mz_previous_normal_flag(0)
23 {reseed(seed);}
24 
26  : linear_congruential_previous(r.linear_congruential_previous)
27  , mz_array_position(r.mz_array_position)
28  , mz_borrow(r.mz_borrow)
29  , mz_previous_normal_flag(r.mz_previous_normal_flag)
30 {
31  for (unsigned int i=0;i<vnl_random_array_size;++i)
32  {
33  mz_seed_array[i] = r.mz_seed_array[i];
34  mz_array[i] = r.mz_array[i];
35  }
36 }
37 
39 {
44  for (unsigned int i=0;i<vnl_random_array_size;++i)
45  {
46  mz_seed_array[i] = r.mz_seed_array[i];
47  mz_array[i] = r.mz_array[i];
48  }
49  return *this;
50 }
51 
52 vnl_random::vnl_random() : mz_array_position(0UL), mz_borrow(0), mz_previous_normal_flag(0)
53 {
54  reseed();
55 }
56 
58 {
59  for (unsigned int i=0;i<vnl_random_array_size;++i)
60  {
61  mz_seed_array[i] = 0;
62  mz_array[i] = 0;
63  }
64 }
65 
67 {
68  reseed((unsigned long)std::time(nullptr));
69 }
70 
71 void vnl_random::reseed(unsigned long seed)
72 {
73  mz_array_position = 0UL;
74  mz_borrow = 0;
75 
77  // Use the lc generator to fill the array
78  for (unsigned int i=0;i<vnl_random_array_size;++i)
79  {
81  mz_array[i] = mz_seed_array[i];
82  }
83 
84  // Warm up with 1000 randoms
85  for (int j=0;j<1000;j++) lrand32();
86 }
87 
88 void vnl_random::reseed(const unsigned long seed[vnl_random_array_size])
89 {
90  mz_array_position = 0UL;
91  mz_borrow = 0L;
92 
93  for (unsigned int i=0;i<vnl_random_array_size;++i)
94  {
95  mz_array[i] = seed[i];
96  mz_seed_array[i] = seed[i];
97  }
98 }
99 
101 {
102  mz_array_position = 0UL;
103 
104  for (unsigned int i=0;i<vnl_random_array_size;++i)
105  {
106  mz_array[i] = mz_seed_array[i];
107  }
108 }
109 
111 {
113  {
115  return mz_previous_normal;
116  }
117  else
118  {
119  double x,y,r2;
120  do
121  {
122  x = drand32(-1.0,1.0);
123  y = drand32(-1.0,1.0);
124  r2 = x*x+y*y;
125  }
126  while (r2 >=1.0 || r2 == 0.0);
127  double fac = std::sqrt(-2.0*std::log(r2)/r2);
128  mz_previous_normal = x*fac;
130  return y*fac;
131  }
132 }
133 
134 
135 //: Random value from a unit normal distribution about zero
136 // Uses a drand64() as its underlying generator.
137 // Because the function uses a probability transform, the randomness (and
138 // quantisation) is non-linearly dependent on the value. The further the sample
139 // is from zero, the lower the number of bits on which it is random.
141 {
143  {
145  return mz_previous_normal;
146  }
147  else
148  {
149  double x,y,r2;
150  do
151  {
152  x = drand64(-1.0,1.0);
153  y = drand64(-1.0,1.0);
154  r2 = x*x+y*y;
155  }
156  while (r2 >=1.0 || r2 == 0.0);
157  double fac = std::sqrt(-2.0*std::log(r2)/r2);
158  mz_previous_normal = x*fac;
160  return y*fac;
161  }
162 }
163 
164 unsigned long vnl_random::lrand32()
165 {
167  unsigned long p2 = (p1 - mz_array[mz_array_position] - mz_borrow)&0xffffffff;
168  if (p2 < p1) mz_borrow = 0;
169  if (p2 > p1) mz_borrow = 1;
172  return p2;
173 }
174 
175 int vnl_random::lrand32(int lower, int upper)
176 {
177  assert(lower <= upper);
178 
179  // Note: we have to reject some numbers otherwise we get a very slight bias
180  // towards the lower part of the range lower - upper. See below
181 
182  unsigned long range = upper-lower+1;
183  unsigned long denom = 0xffffffff/range;
184  unsigned long ran;
185  while ((ran=lrand32()) >= denom*range) ;
186  return lower + int(ran/denom);
187 }
188 
189 
190 int vnl_random::lrand32(int lower, int upper, int &count)
191 {
192  assert(lower <= upper);
193 
194  // Note: we have to reject some numbers otherwise we get a very slight bias
195  // towards the lower part of the range lower - upper. Hence this is a "count"
196  // version of the above function that returns the number of lrand32()
197  // calls made.
198 
199  unsigned long range = upper-lower+1;
200  unsigned long denom = 0xffffffff/range;
201  unsigned long ran;
202  count = 1;
203  while ((ran=lrand32())>=denom*range) ++count;
204  return lower + int(ran/denom);
205 }
206 
207 double vnl_random::drand32(double lower, double upper)
208 {
209  assert(lower <= upper);
210  return (double(lrand32())/0xffffffff)*(upper-lower) + lower;
211 }
212 
213 double vnl_random::drand64(double lower, double upper)
214 {
215  assert(lower <= upper);
216  return (double(lrand32())/0xffffffff + double(lrand32())/(double(0xffffffff)*double(0xffffffff)))*(upper-lower) + lower;
217 }
int mz_borrow
Definition: vnl_random.h:32
double normal64()
Random value from a unit normal distribution about zero.
Definition: vnl_random.cxx:140
unsigned long linear_congruential_lrand32()
Definition: vnl_random.cxx:10
unsigned long mz_array[vnl_random_array_size]
Definition: vnl_random.h:30
double normal()
Random value from a unit normal distribution about zero.
Definition: vnl_random.cxx:110
unsigned long mz_seed_array[vnl_random_array_size]
Definition: vnl_random.h:29
void restart()
This restarts the sequence of random numbers.
Definition: vnl_random.cxx:100
A superior random number generator.
Definition: vnl_random.h:25
double mz_previous_normal
Definition: vnl_random.h:35
~vnl_random()
Destructor.
Definition: vnl_random.cxx:57
vnl_random()
Default constructor.
Definition: vnl_random.cxx:52
unsigned int mz_array_position
Definition: vnl_random.h:31
unsigned long linear_congruential_previous
Definition: vnl_random.h:28
A superior random number generator.
int mz_previous_normal_flag
Definition: vnl_random.h:36
double drand32()
Generates a random double in the range 0 <= x <= 1 with 32 bit randomness.
Definition: vnl_random.h:118
double drand64()
Generates a random double in the range 0 <= x <= 1 with 64 bit randomness.
Definition: vnl_random.h:130
constexpr unsigned int vnl_random_array_size
Definition: vnl_random.h:14
unsigned long lrand32()
Generates a random unsigned 32-bit number.
Definition: vnl_random.cxx:164
void reseed()
Starts a new non-deterministic sequence from an already declared generator.
Definition: vnl_random.cxx:66
vnl_random & operator=(const vnl_random &)
Copy operator.
Definition: vnl_random.cxx:38