2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
|
|
|
|
#include "trandom.h"
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TRandom::RANDOM_FLOAT_TYPE TRandom::RandomFloatType =
|
|
|
|
TRandom::RANDOM_FLOAT_TYPE_NONE;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TRandom::TRandom(UINT _seed) : seed(_seed) {
|
|
|
|
if (RandomFloatType == TRandom::RANDOM_FLOAT_TYPE_NONE) setRandomFloatType();
|
|
|
|
reset();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
TRandom::~TRandom() {}
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TRandom::setSeed(UINT s) {
|
|
|
|
seed = s;
|
|
|
|
reset();
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void TRandom::reset() {
|
|
|
|
UINT uj, uk;
|
|
|
|
int i, ii, k;
|
|
|
|
|
|
|
|
assert(sizeof(UINT) == 32 / 8);
|
|
|
|
|
|
|
|
uj = 161803398 - seed;
|
|
|
|
ran[55] = uj;
|
|
|
|
uk = 1;
|
|
|
|
for (i = 1; i <= 54; i++) {
|
|
|
|
ii = (21 * i) % 55;
|
|
|
|
ran[ii] = uk;
|
|
|
|
uk = uj - uk;
|
|
|
|
uj = ran[ii];
|
|
|
|
}
|
|
|
|
for (k = 1; k <= 4; k++)
|
|
|
|
for (i = 1; i <= 55; i++) ran[i] -= ran[1 + (i + 30) % 55];
|
|
|
|
idx1 = 55;
|
|
|
|
idx2 = 31;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
inline void TRandom::setRandomFloatType() {
|
|
|
|
UINT u;
|
|
|
|
|
|
|
|
assert(sizeof(float) == sizeof(UINT));
|
|
|
|
u = 0x3f800000;
|
|
|
|
if ((*(float *)&u) == 1.0F)
|
|
|
|
RandomFloatType = RANDOM_FLOAT_TYPE_1;
|
|
|
|
else {
|
|
|
|
u = 0x0000803f;
|
|
|
|
if ((*(float *)&u) == 1.0F)
|
|
|
|
RandomFloatType = RANDOM_FLOAT_TYPE_2;
|
|
|
|
else
|
|
|
|
assert(0);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
inline UINT TRandom::getNextUINT() {
|
|
|
|
idx1++;
|
|
|
|
if (idx1 == 56) idx1 = 1;
|
|
|
|
idx2++;
|
|
|
|
if (idx2 == 56) idx2 = 1;
|
|
|
|
ran[idx1] = ran[idx1] - ran[idx2];
|
|
|
|
return ran[idx1];
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
UINT TRandom::getUInt(UINT end) // [0,end[
|
2016-03-19 06:57:51 +13:00
|
|
|
{
|
2016-06-15 18:43:10 +12:00
|
|
|
if (end == 0) return 0;
|
|
|
|
UINT u = getNextUINT();
|
|
|
|
if (end == c_maxuint) return u;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
return u % end;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
int TRandom::getInt(int begin, int end) // [begin, end[
|
2016-03-19 06:57:51 +13:00
|
|
|
{
|
2016-06-15 18:43:10 +12:00
|
|
|
assert(end >= begin);
|
|
|
|
int limit = end - begin;
|
|
|
|
if (limit == 0) // end == begin
|
|
|
|
return begin;
|
|
|
|
UINT u = getNextUINT();
|
|
|
|
return u % limit + begin;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
float TRandom::getFloat() // [0,1[
|
2016-03-19 06:57:51 +13:00
|
|
|
{
|
2016-06-15 18:43:10 +12:00
|
|
|
UINT u = getNextUINT();
|
|
|
|
|
|
|
|
switch (RandomFloatType) {
|
|
|
|
case RANDOM_FLOAT_TYPE_1:
|
2020-04-12 17:19:20 +12:00
|
|
|
u = ((u >> 5) & 0x007fffff) | 0x3f800000;
|
2016-06-15 18:43:10 +12:00
|
|
|
break;
|
|
|
|
case RANDOM_FLOAT_TYPE_2:
|
2020-04-12 17:19:20 +12:00
|
|
|
u = (u & 0xffff7f00) | 0x0000803f;
|
2016-06-15 18:43:10 +12:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
u = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return (*(float *)&u) - 1.0F;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
float TRandom::getFloat(float end) // [0, end[
|
2016-03-19 06:57:51 +13:00
|
|
|
{
|
2016-06-15 18:43:10 +12:00
|
|
|
return getFloat() * end;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
float TRandom::getFloat(float begin, float end) // [begin, end[
|
2016-03-19 06:57:51 +13:00
|
|
|
{
|
2016-06-15 18:43:10 +12:00
|
|
|
assert(end >= begin);
|
|
|
|
return (getFloat() * (end - begin)) + begin;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool TRandom::getBool() {
|
|
|
|
UINT u = getNextUINT();
|
|
|
|
return u & 1;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
double TRandom::getDouble() // [0,1[
|
2016-03-19 06:57:51 +13:00
|
|
|
{
|
2016-06-15 18:43:10 +12:00
|
|
|
return getFloat();
|
2016-03-19 06:57:51 +13:00
|
|
|
#ifdef DA_RIVEDERE_O_PROPRIO_IMPLEMENTARE
|
2016-06-15 18:43:10 +12:00
|
|
|
UINT low = getNextUINT();
|
|
|
|
UINT high = getNextUINT();
|
|
|
|
double value = 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void *ptr = &value;
|
|
|
|
UINT *retL = (UINT *)ptr;
|
|
|
|
UINT *retH = retL + 1;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
/*
|
|
|
|
// questa parte e' stata commentata perche' su tutte le piattaforme il tipo
|
2016-06-15 18:43:10 +12:00
|
|
|
//di float e' RANDOM_FLOAT_TYPE_1ma su irix c'e' bisogno di eseguire le
|
2016-03-19 06:57:51 +13:00
|
|
|
//istruzioni sotto RANDOM_FLOAT_TYPE_2
|
|
|
|
switch (RandomFloatType)
|
|
|
|
{
|
|
|
|
case RANDOM_FLOAT_TYPE_1:
|
|
|
|
*retH = high;
|
|
|
|
*retH &= 0x00efffff;
|
|
|
|
*retH |= 0x3f000000;
|
|
|
|
|
|
|
|
*retL = low ;
|
|
|
|
// vecchi commenti
|
|
|
|
// *retH = high;
|
|
|
|
// *retL = (low >> 5) & 0x007fffff | 0x3ff00000;
|
|
|
|
|
|
|
|
return value;
|
|
|
|
break;
|
|
|
|
case RANDOM_FLOAT_TYPE_2: *retH = low;
|
|
|
|
*retL = (high >> 5) & 0x007fffff | 0x3ff00000;
|
|
|
|
break;
|
2016-06-15 18:43:10 +12:00
|
|
|
//!!!!!occhio andrebbe sopra il break
|
2016-03-19 06:57:51 +13:00
|
|
|
return value-1.0;
|
2016-06-15 18:43:10 +12:00
|
|
|
default: assert (0);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
*/
|
|
|
|
#ifndef __sgi
|
2016-06-15 18:43:10 +12:00
|
|
|
*retH = high;
|
|
|
|
*retH &= 0x007fffff;
|
|
|
|
*retH |= 0x3ff00000;
|
|
|
|
*retL = low;
|
|
|
|
return value - 1.0;
|
2016-03-19 06:57:51 +13:00
|
|
|
#else
|
2016-06-15 18:43:10 +12:00
|
|
|
*retH = low;
|
|
|
|
*retL = (high >> 5) & 0x007fffff | 0x3ff00000;
|
|
|
|
return value - 1.0;
|
2016-03-19 06:57:51 +13:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|