Blob Blame Raw


#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
}