ENH: add generator class for uniform/gaussian random numbers

- can be used in combination with std::generate, or as a substitute
  unary operator to supply random numbers for std::transform.
This commit is contained in:
Mark Olesen 2019-11-21 09:40:00 +01:00 committed by Andrew Heather
parent cc138b0d82
commit 42a9a6ae5a
2 changed files with 185 additions and 3 deletions

View File

@ -31,7 +31,6 @@ Description
\*---------------------------------------------------------------------------*/
#include "Rand48.H"
#include "Random.H"
#include <cstdlib>
@ -218,6 +217,59 @@ int main(int argc, char *argv[])
testPosition(20);
testPosition(3);
// Generators
{
const label n = 20;
List<label> samples(n, Zero);
Random::uniformGeneratorOp<label> gen(0, n-1);
// Test uniformity of random
samples = Zero;
for (label i=0; i < 100000*n; ++i)
{
// Calling with/without parameter is the same
if (i % 3)
{
++samples[gen()];
}
else
{
// Unary ignores any parameter
++samples[gen(3.14159)];
}
}
Info<< nl << "Uniform generator [0," << n << ")\n "
<< flatOutput(samples) << nl;
}
{
Random::gaussianGeneratorOp<scalar> gen;
Info<< "Some gaussian generated values" << nl;
for (label i=0; i < 20; ++i)
{
Info<< ' ';
// Calling with/without parameter is the same
if (i % 3)
{
Info<< gen();
}
else
{
// Unary ignores any parameter
Info<< gen(3.14159);
}
}
Info<< nl;
}
// This should fail (in FULLDEBUG)
const bool throwingError = FatalError.throwExceptions();
try

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2018 OpenCFD Ltd.
Copyright (C) 2017-2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -59,7 +59,7 @@ template<class T> class UList;
class Random
{
// Private data
// Private Data
//- Initial random number seed
label seed_;
@ -85,6 +85,11 @@ class Random
public:
// Forward declarations - generator classes
template<class T> class uniformGeneratorOp;
template<class T> class gaussianGeneratorOp;
// Public Static Data
//- The default seed value (name may change in the future)
@ -203,6 +208,131 @@ template<>
label Random::globalPosition<label>(const label& start, const label& end);
/*---------------------------------------------------------------------------*\
Class Random::uniformGeneratorOp Declaration
\*---------------------------------------------------------------------------*/
//- A generator class returning a uniformly distributed random number
//- on the given interval.
//
// \sa std::generate()
template<class T>
class Random::uniformGeneratorOp
:
public Random
{
// Private data
//- The interval
const T min_;
const T max_;
// Private Member Functions
//- Generate a random number. Treat as mutable.
T generate() const
{
return const_cast<uniformGeneratorOp&>(*this)
.position<T>(min_, max_);
}
public:
// Constructors
//- Construct null or with seed value. Uses default [0,1] interval
explicit uniformGeneratorOp(const label seed = Random::defaultSeed)
:
uniformGeneratorOp(seed, pTraits<T>::zero, pTraits<T>::one)
{}
//- Construct with specified interval, using default seed
uniformGeneratorOp(const T& minval, const T& maxval)
:
uniformGeneratorOp(Random::defaultSeed, minval, maxval)
{}
//- Construct with seed value and specified interval
uniformGeneratorOp(const label seed, const T& minval, const T& maxval)
:
Random(seed),
min_(minval),
max_(maxval)
{}
// Member Operators
//- Generate a random number
T operator()()
{
return generate();
}
//- Ignore parameter and generate a random number, which allows it
//- to be used as a replacement for general unary operators.
template<class U>
T operator()(const U&) const
{
return generate();
}
};
/*---------------------------------------------------------------------------*\
Class Random::gaussianGeneratorOp Declaration
\*---------------------------------------------------------------------------*/
//- A generator class returning a gaussian distributed random number.
//
// \sa std::generate()
template<class T>
class Random::gaussianGeneratorOp
:
public Random
{
// Private Member Functions
//- Generate a random number. Treat as mutable.
T generate() const
{
return const_cast<gaussianGeneratorOp&>(*this)
.GaussNormal<T>();
}
public:
// Constructors
//- Construct null or with seed value. Uses default [0,1] interval
explicit gaussianGeneratorOp(const label seed = Random::defaultSeed)
:
Random(seed)
{}
// Member Operators
//- Generate a random number
T operator()()
{
return generate();
}
//- Ignore parameter and generate a random number, which allows it
//- to be used as a replacement for general unary operators.
template<class U>
T operator()(const U&) const
{
return generate();
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam