/* $Id: weightedrandom.cpp,v 1.6 2005/06/28 13:55:26 chfreund Exp $ */ #include #include "weightedrandom.hpp" #include "serialize.hpp" /**********************************************************/ WeightedRandom::WeightedRandom( const unsigned int seed ) : Random(seed), m_NumIntervals(0), m_Intervals(NULL) { } /**********************************************************/ WeightedRandom::~WeightedRandom() { delete [] m_Intervals; } /**********************************************************/ bool WeightedRandom::setWeights( const int nWeights, const int *const Weights ) { if( (Uint32)nWeights != m_NumIntervals || NULL == Weights ) { // remove present data delete [] m_Intervals; m_Intervals = NULL; m_NumIntervals = 0; // get memory for new weights if( nWeights > 0 && Weights != NULL ) { if( !CHECK( NULL != (m_Intervals = NEW Uint32 [nWeights]), "WeightedRandom::setWeights: could not get " "int [%d] for weights -> using uniform " "distribution\n", nWeights ) ) { return false; } } m_NumIntervals = nWeights; } // in any case, here we have the correct value of m_NumIntervals // and an corresponding large memory block at m_Intervals, BUT // ONLY, if Weights != NULL if( m_NumIntervals > 0 && m_Intervals != NULL ) { m_Intervals[0] = Weights[0]; for( Uint32 i = 1; i < m_NumIntervals; i++ ) { DBG(1) { if( !CHECK( Weights[i] >= 0, "WeightedRandom::setWeights: weight [%s] = " "%d < 0, should be >= 0 -> using uniform " "distribution\n", i, Weights[i] ) ) { delete [] m_Intervals; m_Intervals = NULL; return false; } } m_Intervals[i] = (Uint32)(m_Intervals[i-1] + Weights[i]); } // in debug mode check the sum of the random weights DBG( 1 ) { ASSERT( m_Intervals[m_NumIntervals-1] > 0, "WeightedRandom::setWeights: the sum of all " "weights is %d, but must be > 0.\n", m_Intervals[m_NumIntervals-1] ); } } return true; } /**********************************************************/ Uint32 WeightedRandom::getWeightedUint32() { Uint32 rndUint32 = Random::getUint32(); // if no weights have been set, this call is identical // to a call of the base class function getUint32. if( m_NumIntervals == 0 ) return rndUint32; // if only the number of weights was specified, but not the // weights itselves, a uniformly distributed value is returned. if( m_Intervals == 0 ) return rndUint32 % m_NumIntervals; rndUint32 %= m_Intervals[m_NumIntervals-1]; for( Uint32 i = 0; i < m_NumIntervals; i++ ) { if( rndUint32 < m_Intervals[i] ) return i; } CHECK( false, "WeightedRandom::getWeightedUint32: Error in " "algorithm. This line should never be reached\n" ); // only to suppress compiler warnings. This line should // never be reached return 0; } /**********************************************************/ Uint32 WeightedRandom::getSerializeBufferSize() const { return Serialize::sizeOf( m_NumIntervals ) + Serialize::sizeOf() + ( m_Intervals != NULL ? m_NumIntervals * Serialize::sizeOf() : 0) + Random::getSerializeBufferSize() // adds additional size for debugging (see serialize.hpp), // but only, if the tags are used PLUS_TAG_SIZE( 1 ); } /**********************************************************/ void WeightedRandom::serialize( Uint8*& bufferPointer ) const { START_SERIALIZED_SIZE_CHECK( bufferPointer ); Random::serialize( bufferPointer ); Uint32 bufferSize = m_Intervals != NULL ? m_NumIntervals : 0; // write number of intervals Serialize::serialize( m_NumIntervals, bufferPointer ); // write the used buffer size Serialize::serialize( bufferSize, bufferPointer ); // write the Intervals Serialize::serialize( bufferSize, m_Intervals, bufferPointer ); SERIALIZE_TAG( bufferPointer ); END_SERIALIZED_SIZE_CHECK( bufferPointer, WeightedRandom ); } /**********************************************************/ void WeightedRandom::deserialize( Uint8*& bufferPointer ) { Uint32 bufferSize, oldNumIntervals = m_NumIntervals; Random::deserialize( bufferPointer ); // deserialize the number of intervals Serialize::deserialize( bufferPointer, m_NumIntervals ); // deserialize the used buffer size Serialize::deserialize( bufferPointer, bufferSize ); // create the interval size, if necessary if( bufferSize > 0 ) { if( bufferSize != oldNumIntervals ) { delete [] m_Intervals; ASSERT( NULL != (m_Intervals = NEW Uint32 [bufferSize]), "WeightedRandom::deserialize: could not create " "interval array of size %d\n", bufferSize ); m_NumIntervals = bufferSize; } Serialize::deserialize( bufferSize, bufferPointer, m_Intervals ); } else { delete [] m_Intervals; m_Intervals = NULL; m_NumIntervals = 0; } DESERIALIZE_TAG( bufferPointer ); } /**********************************************************/