tahoma2d/toonz/sources/common/tcore/trandom.cpp
2016-06-15 15:43:10 +09:00

195 lines
4.6 KiB
C++

#include "trandom.h"
TRandom::RANDOM_FLOAT_TYPE TRandom::RandomFloatType =
TRandom::RANDOM_FLOAT_TYPE_NONE;
TRandom::TRandom(UINT _seed) : seed(_seed) {
if (RandomFloatType == TRandom::RANDOM_FLOAT_TYPE_NONE) setRandomFloatType();
reset();
}
//--------------------------------------------------------------------------
TRandom::~TRandom() {}
//--------------------------------------------------------------------------
void TRandom::setSeed(UINT s) {
seed = s;
reset();
}
//--------------------------------------------------------------------------
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;
}
//--------------------------------------------------------------------------
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);
}
}
//--------------------------------------------------------------------------
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];
}
//--------------------------------------------------------------------------
UINT TRandom::getUInt(UINT end) // [0,end[
{
if (end == 0) return 0;
UINT u = getNextUINT();
if (end == c_maxuint) return u;
return u % end;
}
//--------------------------------------------------------------------------
int TRandom::getInt(int begin, int end) // [begin, end[
{
assert(end >= begin);
int limit = end - begin;
if (limit == 0) // end == begin
return begin;
UINT u = getNextUINT();
return u % limit + begin;
}
//--------------------------------------------------------------------------
float TRandom::getFloat() // [0,1[
{
UINT u = getNextUINT();
switch (RandomFloatType) {
case RANDOM_FLOAT_TYPE_1:
u = (u >> 5) & 0x007fffff | 0x3f800000;
break;
case RANDOM_FLOAT_TYPE_2:
u = u & 0xffff7f00 | 0x0000803f;
break;
default:
assert(0);
u = 0;
break;
}
return (*(float *)&u) - 1.0F;
}
//--------------------------------------------------------------------------
float TRandom::getFloat(float end) // [0, end[
{
return getFloat() * end;
}
//--------------------------------------------------------------------------
float TRandom::getFloat(float begin, float end) // [begin, end[
{
assert(end >= begin);
return (getFloat() * (end - begin)) + begin;
}
//--------------------------------------------------------------------------
bool TRandom::getBool() {
UINT u = getNextUINT();
return u & 1;
}
//--------------------------------------------------------------------------
double TRandom::getDouble() // [0,1[
{
return getFloat();
#ifdef DA_RIVEDERE_O_PROPRIO_IMPLEMENTARE
UINT low = getNextUINT();
UINT high = getNextUINT();
double value = 0;
void *ptr = &value;
UINT *retL = (UINT *)ptr;
UINT *retH = retL + 1;
/*
// questa parte e' stata commentata perche' su tutte le piattaforme il tipo
//di float e' RANDOM_FLOAT_TYPE_1ma su irix c'e' bisogno di eseguire le
//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;
//!!!!!occhio andrebbe sopra il break
return value-1.0;
default: assert (0);
}
return -1;
*/
#ifndef __sgi
*retH = high;
*retH &= 0x007fffff;
*retH |= 0x3ff00000;
*retL = low;
return value - 1.0;
#else
*retH = low;
*retL = (high >> 5) & 0x007fffff | 0x3ff00000;
return value - 1.0;
#endif
#endif
}