mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
STYLE: floor/truncate instead of rounding for Random::position (issue #865)
- affects random integer ranges. Simpler to extend the range by one and floor (truncate) instead of rounding using odd intervals.
This commit is contained in:
@ -68,6 +68,22 @@ double randomFraction(const uint64_t bits)
|
|||||||
|
|
||||||
using namespace Foam;
|
using namespace Foam;
|
||||||
|
|
||||||
|
// Test uniformity of random
|
||||||
|
void testPosition(const label n)
|
||||||
|
{
|
||||||
|
List<label> samples(n, Zero);
|
||||||
|
|
||||||
|
Random rnd(123456);
|
||||||
|
for (label i=0; i < 100000*n; ++i)
|
||||||
|
{
|
||||||
|
++samples[rnd.position<label>(0,n-1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
Info<< nl << "uniform [0," << n << ")\n "
|
||||||
|
<< flatOutput(samples) << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Output with cout instead of Info to keep values unsigned on output
|
// Output with cout instead of Info to keep values unsigned on output
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::setw;
|
using std::setw;
|
||||||
@ -175,20 +191,24 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test uniformity of random
|
// Test uniformity of random
|
||||||
|
testPosition(20);
|
||||||
|
testPosition(3);
|
||||||
|
|
||||||
|
// This should fail (in FULLDEBUG)
|
||||||
|
const bool throwingError = FatalError.throwExceptions();
|
||||||
|
try
|
||||||
{
|
{
|
||||||
List<label> samples(20, Zero);
|
Info<<"Random position(10,5): "
|
||||||
|
<< Random().position<label>(10, 5) << endl;
|
||||||
Random rnd(123456);
|
}
|
||||||
for (label i=0; i < 1000*samples.size(); ++i)
|
catch (Foam::error& err)
|
||||||
{
|
{
|
||||||
++samples[rnd.position<label>(0,19)];
|
Info<< "Caught FatalError " << err << nl << endl;
|
||||||
}
|
|
||||||
|
|
||||||
Info<< nl << "uniform [0,20)" << nl << " "
|
|
||||||
<< flatOutput(samples) << nl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Info<< nl << "Done." << endl;
|
FatalError.throwExceptions(throwingError);
|
||||||
|
|
||||||
|
Info<< "\nDone" << nl << endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,9 +121,24 @@ Foam::scalar Foam::Random::position
|
|||||||
template<>
|
template<>
|
||||||
Foam::label Foam::Random::position(const label& start, const label& end)
|
Foam::label Foam::Random::position(const label& start, const label& end)
|
||||||
{
|
{
|
||||||
// Extend range from [0, N-1] to (-0.5, N-0.5) to ensure that round()
|
#ifdef FULLDEBUG
|
||||||
// results in the same number density at the ends.
|
if (start > end)
|
||||||
return start + round(scalar01()*((end - start) + 0.998) - 0.499);
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "start index " << start << " > end index " << end << nl
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Extend the upper sampling range by 1 and floor the result.
|
||||||
|
// Since the range is non-negative, can use integer truncation
|
||||||
|
// instead using floor().
|
||||||
|
|
||||||
|
const label val = start + label(scalar01()*(end - start + 1));
|
||||||
|
|
||||||
|
// Rare case when scalar01() returns exactly 1.000 and the truncated
|
||||||
|
// value would be out of range.
|
||||||
|
return min(val, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -61,10 +61,10 @@ class Random
|
|||||||
//- Initial random number seed
|
//- Initial random number seed
|
||||||
label seed_;
|
label seed_;
|
||||||
|
|
||||||
//- Random number generator on the int32 interval [0, 2^31)
|
//- Random number generator on the int32 interval [0,2^31)
|
||||||
Rand48 generator_;
|
Rand48 generator_;
|
||||||
|
|
||||||
//- Uniform distribution on the scalar interval [0, 1]
|
//- Uniform distribution on the scalar interval [0,1]
|
||||||
std::uniform_real_distribution<scalar> uniform01_;
|
std::uniform_real_distribution<scalar> uniform01_;
|
||||||
|
|
||||||
//- Is there a gaussian sample cached?
|
//- Is there a gaussian sample cached?
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
Random(const Random& r, const bool reset = false);
|
Random(const Random& r, const bool reset = false);
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
//- Destructor
|
||||||
~Random() = default;
|
~Random() = default;
|
||||||
|
|
||||||
|
|
||||||
@ -111,20 +111,20 @@ public:
|
|||||||
//- Return a random bit
|
//- Return a random bit
|
||||||
inline int bit();
|
inline int bit();
|
||||||
|
|
||||||
//- Return a sample whose components lie in the range 0-1
|
//- Return a sample whose components lie in the range [0,1]
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type sample01();
|
Type sample01();
|
||||||
|
|
||||||
//- Return a sample whose components are normally distributed
|
//- Return a sample whose components are normally distributed
|
||||||
// with zero mean and unity variance N(0, 1)
|
//- with zero mean and unity variance N(0,1)
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type GaussNormal();
|
Type GaussNormal();
|
||||||
|
|
||||||
//- Return a sample between start and end
|
//- Return a sample on the interval [start,end]
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type position(const Type& start, const Type& end);
|
Type position(const Type& start, const Type& end);
|
||||||
|
|
||||||
//- Randomise value in the range 0-1
|
//- Randomise value in the range [0,1]
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void randomise01(Type& value);
|
void randomise01(Type& value);
|
||||||
|
|
||||||
@ -135,16 +135,16 @@ public:
|
|||||||
|
|
||||||
// Global random numbers - consistent across all processors
|
// Global random numbers - consistent across all processors
|
||||||
|
|
||||||
//- Return a sample whose components lie in the range 0-1
|
//- Return a sample whose components lie in the range [0,1]
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type globalSample01();
|
Type globalSample01();
|
||||||
|
|
||||||
//- Return a sample whose components are normally distributed
|
//- Return a sample whose components are normally distributed
|
||||||
// with zero mean and unity variance N(0, 1)
|
//- with zero mean and unity variance N(0,1)
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type globalGaussNormal();
|
Type globalGaussNormal();
|
||||||
|
|
||||||
//- Return a sample between start and end
|
//- Return a sample on the interval [start,end]
|
||||||
template<class Type>
|
template<class Type>
|
||||||
Type globalPosition(const Type& start, const Type& end);
|
Type globalPosition(const Type& start, const Type& end);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user