📄 vnl_random.cxx
字号:
// This is core/vnl/vnl_random.cxx
#ifdef VCL_NEEDS_PRAGMA_INTERFACE
#pragma implementation
#endif
//:
// \file
#include "vnl_random.h"
#include <vcl_ctime.h>
#include <vcl_cmath.h>
#include <vcl_cassert.h>
unsigned long vnl_random::linear_congruential_lrand32()
{
return linear_congruential_previous = (linear_congruential_previous*linear_congruential_multiplier + 1)&0xffffffff;
}
//: Construct with seed
vnl_random::vnl_random(unsigned long seed)
: mz_array_position(0L), mz_borrow(0), mz_previous_normal_flag(0)
{reseed(seed);}
//: Construct with seed
vnl_random::vnl_random(unsigned long seed[vnl_random_array_size])
: mz_array_position(0L), mz_borrow(0), mz_previous_normal_flag(0)
{reseed(seed);}
vnl_random::vnl_random(const vnl_random& r)
: linear_congruential_previous(r.linear_congruential_previous)
, mz_array_position(r.mz_array_position)
, mz_borrow(r.mz_borrow)
, mz_previous_normal_flag(r.mz_previous_normal_flag)
{
for (int i=0;i<vnl_random_array_size;++i)
{
mz_seed_array[i] = r.mz_seed_array[i];
mz_array[i] = r.mz_array[i];
}
}
vnl_random& vnl_random::operator=(const vnl_random& r)
{
linear_congruential_previous=r.linear_congruential_previous;
mz_array_position=r.mz_array_position;
mz_borrow=r.mz_borrow;
mz_previous_normal_flag=r.mz_previous_normal_flag;
for (int i=0;i<vnl_random_array_size;++i)
{
mz_seed_array[i] = r.mz_seed_array[i];
mz_array[i] = r.mz_array[i];
}
return *this;
}
vnl_random::vnl_random() : mz_array_position(0), mz_borrow(0), mz_previous_normal_flag(0)
{
reseed();
}
vnl_random::~vnl_random()
{
for (int i=0;i<vnl_random_array_size;++i)
{
mz_seed_array[i] = 0;
mz_array[i] = 0;
}
}
void vnl_random::reseed()
{
reseed((unsigned long)vcl_time(NULL));
}
void vnl_random::reseed(unsigned long seed)
{
mz_array_position = 0L;
mz_borrow = 0L;
linear_congruential_previous = seed;
// Use the lc generator to fill the array
for (int i=0;i<vnl_random_array_size;++i)
{
mz_seed_array[i] = linear_congruential_lrand32();
mz_array[i] = mz_seed_array[i];
}
// Warm up with 1000 randoms
for (int j=0;j<1000;j++) lrand32();
}
void vnl_random::reseed(unsigned long seed[vnl_random_array_size])
{
mz_array_position = 0L;
mz_borrow = 0L;
for (int i=0;i<vnl_random_array_size;++i)
{
mz_array[i] = seed[i];
mz_seed_array[i] = seed[i];
}
}
void vnl_random::restart()
{
mz_array_position = 0L;
for (int i=0;i<vnl_random_array_size;++i)
{
mz_array[i] = mz_seed_array[i];
}
}
double vnl_random::normal()
{
if (mz_previous_normal_flag)
{
mz_previous_normal_flag = 0;
return mz_previous_normal;
}
else
{
double x,y,r2;
do
{
x = drand32(-1.0,1.0);
y = drand32(-1.0,1.0);
r2 = x*x+y*y;
}
while (r2 >=1.0 || r2 == 0.0);
double fac = vcl_sqrt(-2.0*vcl_log(r2)/r2);
mz_previous_normal = x*fac;
mz_previous_normal_flag = 1;
return y*fac;
}
}
//: Random value from a unit normal distribution about zero
// Uses a drand64() as its underlying generator.
// Because the function uses a probability transform, the randomness (and
// quantisation) is non-linearly dependent on the value. The further the sample
// is from zero, the lower the number of bits on which it is random.
double vnl_random::normal64()
{
if (mz_previous_normal_flag)
{
mz_previous_normal_flag = 0;
return mz_previous_normal;
}
else
{
double x,y,r2;
do
{
x = drand64(-1.0,1.0);
y = drand64(-1.0,1.0);
r2 = x*x+y*y;
}
while (r2 >=1.0 || r2 == 0.0);
double fac = vcl_sqrt(-2.0*vcl_log(r2)/r2);
mz_previous_normal = x*fac;
mz_previous_normal_flag = 1;
return y*fac;
}
}
unsigned long vnl_random::lrand32()
{
unsigned long p1 = mz_array[(vnl_random_array_size + mz_array_position - mz_previous1)%vnl_random_array_size];
unsigned long p2 = (p1 - mz_array[mz_array_position] - mz_borrow)&0xffffffff;
if (p2 < p1) mz_borrow = 0;
if (p2 > p1) mz_borrow = 1;
mz_array[mz_array_position] = p2;
mz_array_position = (++mz_array_position)%vnl_random_array_size;
return p2;
}
int vnl_random::lrand32(int lower, int upper)
{
assert(lower <= upper);
// Note: we have to reject some numbers otherwise we get a very slight bias
// towards the lower part of the range lower - upper. See below
unsigned long range = upper-lower+1;
unsigned long denom = 0xffffffff/range;
unsigned long ran;
while ((ran=lrand32()) >= denom*range) ;
return lower + int(ran/denom);
}
int vnl_random::lrand32(int lower, int upper, int &count)
{
assert(lower <= upper);
// Note: we have to reject some numbers otherwise we get a very slight bias
// towards the lower part of the range lower - upper. Hence this is a "count"
// version of the above function that returns the number of lrand32()
// calls made.
unsigned long range = upper-lower+1;
unsigned long denom = 0xffffffff/range;
unsigned long ran;
count = 1;
while ((ran=lrand32())>=denom*range) ++count;
return lower + int(ran/denom);
}
double vnl_random::drand32(double lower, double upper)
{
assert(lower <= upper);
return (double(lrand32())/0xffffffff)*(upper-lower) + lower;
}
double vnl_random::drand64(double lower, double upper)
{
assert(lower <= upper);
return (double(lrand32())/0xffffffff + double(lrand32())/(double(0xffffffff)*double(0xffffffff)))*(upper-lower) + lower;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -