Go to the documentation of this file.00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "vnl_random.h"
00009 #include <vcl_ctime.h>
00010 #include <vcl_cmath.h>
00011 #include <vcl_cassert.h>
00012
00013 unsigned long vnl_random::linear_congruential_lrand32()
00014 {
00015 return linear_congruential_previous = (linear_congruential_previous*linear_congruential_multiplier + 1)&0xffffffff;
00016 }
00017
00018
00019 vnl_random::vnl_random(unsigned long seed)
00020 : linear_congruential_previous(seed), mz_array_position(0UL), mz_borrow(0), mz_previous_normal_flag(0)
00021 {reseed(seed);}
00022
00023
00024 vnl_random::vnl_random(unsigned long seed[vnl_random_array_size])
00025 : mz_array_position(0UL), mz_borrow(0), mz_previous_normal_flag(0)
00026 {reseed(seed);}
00027
00028 vnl_random::vnl_random(const vnl_random& r)
00029 : linear_congruential_previous(r.linear_congruential_previous)
00030 , mz_array_position(r.mz_array_position)
00031 , mz_borrow(r.mz_borrow)
00032 , mz_previous_normal_flag(r.mz_previous_normal_flag)
00033 {
00034 for (unsigned int i=0;i<vnl_random_array_size;++i)
00035 {
00036 mz_seed_array[i] = r.mz_seed_array[i];
00037 mz_array[i] = r.mz_array[i];
00038 }
00039 }
00040
00041 vnl_random& vnl_random::operator=(const vnl_random& r)
00042 {
00043 linear_congruential_previous=r.linear_congruential_previous;
00044 mz_array_position=r.mz_array_position;
00045 mz_borrow=r.mz_borrow;
00046 mz_previous_normal_flag=r.mz_previous_normal_flag;
00047 for (unsigned int i=0;i<vnl_random_array_size;++i)
00048 {
00049 mz_seed_array[i] = r.mz_seed_array[i];
00050 mz_array[i] = r.mz_array[i];
00051 }
00052 return *this;
00053 }
00054
00055 vnl_random::vnl_random() : mz_array_position(0UL), mz_borrow(0), mz_previous_normal_flag(0)
00056 {
00057 reseed();
00058 }
00059
00060 vnl_random::~vnl_random()
00061 {
00062 for (unsigned int i=0;i<vnl_random_array_size;++i)
00063 {
00064 mz_seed_array[i] = 0;
00065 mz_array[i] = 0;
00066 }
00067 }
00068
00069 void vnl_random::reseed()
00070 {
00071 reseed((unsigned long)vcl_time(NULL));
00072 }
00073
00074 void vnl_random::reseed(unsigned long seed)
00075 {
00076 mz_array_position = 0UL;
00077 mz_borrow = 0;
00078
00079 linear_congruential_previous = seed;
00080
00081 for (unsigned int i=0;i<vnl_random_array_size;++i)
00082 {
00083 mz_seed_array[i] = linear_congruential_lrand32();
00084 mz_array[i] = mz_seed_array[i];
00085 }
00086
00087
00088 for (int j=0;j<1000;j++) lrand32();
00089 }
00090
00091 void vnl_random::reseed(unsigned long seed[vnl_random_array_size])
00092 {
00093 mz_array_position = 0UL;
00094 mz_borrow = 0L;
00095
00096 for (unsigned int i=0;i<vnl_random_array_size;++i)
00097 {
00098 mz_array[i] = seed[i];
00099 mz_seed_array[i] = seed[i];
00100 }
00101 }
00102
00103 void vnl_random::restart()
00104 {
00105 mz_array_position = 0UL;
00106
00107 for (unsigned int i=0;i<vnl_random_array_size;++i)
00108 {
00109 mz_array[i] = mz_seed_array[i];
00110 }
00111 }
00112
00113 double vnl_random::normal()
00114 {
00115 if (mz_previous_normal_flag)
00116 {
00117 mz_previous_normal_flag = 0;
00118 return mz_previous_normal;
00119 }
00120 else
00121 {
00122 double x,y,r2;
00123 do
00124 {
00125 x = drand32(-1.0,1.0);
00126 y = drand32(-1.0,1.0);
00127 r2 = x*x+y*y;
00128 }
00129 while (r2 >=1.0 || r2 == 0.0);
00130 double fac = vcl_sqrt(-2.0*vcl_log(r2)/r2);
00131 mz_previous_normal = x*fac;
00132 mz_previous_normal_flag = 1;
00133 return y*fac;
00134 }
00135 }
00136
00137
00138
00139
00140
00141
00142
00143 double vnl_random::normal64()
00144 {
00145 if (mz_previous_normal_flag)
00146 {
00147 mz_previous_normal_flag = 0;
00148 return mz_previous_normal;
00149 }
00150 else
00151 {
00152 double x,y,r2;
00153 do
00154 {
00155 x = drand64(-1.0,1.0);
00156 y = drand64(-1.0,1.0);
00157 r2 = x*x+y*y;
00158 }
00159 while (r2 >=1.0 || r2 == 0.0);
00160 double fac = vcl_sqrt(-2.0*vcl_log(r2)/r2);
00161 mz_previous_normal = x*fac;
00162 mz_previous_normal_flag = 1;
00163 return y*fac;
00164 }
00165 }
00166
00167 unsigned long vnl_random::lrand32()
00168 {
00169 unsigned long p1 = mz_array[(vnl_random_array_size + mz_array_position - mz_previous1)%vnl_random_array_size];
00170 unsigned long p2 = (p1 - mz_array[mz_array_position] - mz_borrow)&0xffffffff;
00171 if (p2 < p1) mz_borrow = 0;
00172 if (p2 > p1) mz_borrow = 1;
00173 mz_array[mz_array_position] = p2;
00174 mz_array_position = (mz_array_position+1)%vnl_random_array_size;
00175 return p2;
00176 }
00177
00178 int vnl_random::lrand32(int lower, int upper)
00179 {
00180 assert(lower <= upper);
00181
00182
00183
00184
00185 unsigned long range = upper-lower+1;
00186 unsigned long denom = 0xffffffff/range;
00187 unsigned long ran;
00188 while ((ran=lrand32()) >= denom*range) ;
00189 return lower + int(ran/denom);
00190 }
00191
00192
00193 int vnl_random::lrand32(int lower, int upper, int &count)
00194 {
00195 assert(lower <= upper);
00196
00197
00198
00199
00200
00201
00202 unsigned long range = upper-lower+1;
00203 unsigned long denom = 0xffffffff/range;
00204 unsigned long ran;
00205 count = 1;
00206 while ((ran=lrand32())>=denom*range) ++count;
00207 return lower + int(ran/denom);
00208 }
00209
00210 double vnl_random::drand32(double lower, double upper)
00211 {
00212 assert(lower <= upper);
00213 return (double(lrand32())/0xffffffff)*(upper-lower) + lower;
00214 }
00215
00216 double vnl_random::drand64(double lower, double upper)
00217 {
00218 assert(lower <= upper);
00219 return (double(lrand32())/0xffffffff + double(lrand32())/(double(0xffffffff)*double(0xffffffff)))*(upper-lower) + lower;
00220 }