1 /* $Id: weightedrandom.cpp,v 1.6 2005/06/28 13:55:26 chfreund Exp $ */
2 
3 #include  <new>
4 
5 #include  "weightedrandom.hpp"
6 #include  "serialize.hpp"
7 
8 /**********************************************************/
9 
WeightedRandom(const unsigned int seed)10 WeightedRandom::WeightedRandom( const unsigned int seed )
11               : Random(seed),
12                 m_NumIntervals(0),
13                 m_Intervals(NULL)
14 {
15 }
16 
17 /**********************************************************/
18 
~WeightedRandom()19 WeightedRandom::~WeightedRandom()
20 {
21 	delete [] m_Intervals;
22 }
23 
24 /**********************************************************/
25 
setWeights(const int nWeights,const int * const Weights)26 bool WeightedRandom::setWeights( const int        nWeights,
27                                  const int *const  Weights  )
28 {
29 	if( (Uint32)nWeights != m_NumIntervals || NULL == Weights ) {
30 		// remove present data
31 		delete [] m_Intervals;
32 		m_Intervals    = NULL;
33 		m_NumIntervals = 0;
34 		// get memory for new weights
35 		if( nWeights > 0 && Weights != NULL ) {
36 			if( !CHECK( NULL != (m_Intervals = NEW Uint32 [nWeights]),
37 			            "WeightedRandom::setWeights: could not get "
38 			            "int [%d] for weights -> using uniform "
39 			            "distribution\n", nWeights ) ) {
40 				return false;
41 			}
42 		}
43 		m_NumIntervals = nWeights;
44 	}
45 	// in any case, here we have the correct value of m_NumIntervals
46 	// and an corresponding large memory block at m_Intervals, BUT
47 	// ONLY, if Weights != NULL
48 
49 	if( m_NumIntervals > 0 && m_Intervals != NULL ) {
50 		m_Intervals[0] = Weights[0];
51 		for( Uint32 i = 1; i < m_NumIntervals; i++ ) {
52 			DBG(1) {
53 				if( !CHECK( Weights[i] >= 0,
54 			                "WeightedRandom::setWeights: weight [%s] = "
55 			                "%d < 0, should be >= 0 -> using uniform "
56 			                "distribution\n",
57 			                i, Weights[i] ) ) {
58 					delete [] m_Intervals;
59 					m_Intervals = NULL;
60 					return false;
61 				}
62 			}
63 			m_Intervals[i] = (Uint32)(m_Intervals[i-1] + Weights[i]);
64 		}
65 		// in debug mode check the sum of the random weights
66 		DBG( 1 ) {
67 			ASSERT( m_Intervals[m_NumIntervals-1] > 0,
68 		            "WeightedRandom::setWeights: the sum of all "
69 		            "weights is %d, but must be > 0.\n",
70 		            m_Intervals[m_NumIntervals-1] );
71 		}
72 	}
73 
74 	return true;
75 }
76 
77 /**********************************************************/
78 
getWeightedUint32()79 Uint32 WeightedRandom::getWeightedUint32()
80 {
81 	Uint32 rndUint32 = Random::getUint32();
82 
83 	// if no weights have been set, this call is identical
84 	// to a call of the base class function getUint32.
85 	if( m_NumIntervals == 0 )  return rndUint32;
86 
87 	// if only the number of weights was specified, but not the
88 	// weights itselves, a uniformly distributed value is returned.
89 	if( m_Intervals == 0 )  return rndUint32 % m_NumIntervals;
90 
91 	rndUint32 %= m_Intervals[m_NumIntervals-1];
92 	for( Uint32 i = 0; i < m_NumIntervals; i++ ) {
93 		if( rndUint32 < m_Intervals[i] )  return i;
94 	}
95 
96 	CHECK( false, "WeightedRandom::getWeightedUint32: Error in "
97 	       "algorithm. This line should never be reached\n" );
98 	// only to suppress compiler warnings. This line should
99 	// never be reached
100 	return 0;
101 }
102 
103 /**********************************************************/
104 
getSerializeBufferSize() const105 Uint32 WeightedRandom::getSerializeBufferSize() const
106 {
107 	return    Serialize<Uint32>::sizeOf( m_NumIntervals )
108 	       +  Serialize<Uint32>::sizeOf()
109 	       + (   m_Intervals != NULL
110 	           ? m_NumIntervals * Serialize<Uint32>::sizeOf() : 0)
111 	       +  Random::getSerializeBufferSize()
112 	       // adds additional size for debugging (see serialize.hpp),
113 	       // but only, if the tags are used
114 	          PLUS_TAG_SIZE( 1 );
115 }
116 
117 /**********************************************************/
118 
serialize(Uint8 * & bufferPointer) const119 void WeightedRandom::serialize( Uint8*& bufferPointer ) const
120 {
121 	START_SERIALIZED_SIZE_CHECK( bufferPointer );
122 
123 	Random::serialize( bufferPointer );
124 
125 	Uint32 bufferSize = m_Intervals != NULL ? m_NumIntervals : 0;
126 	// write number of intervals
127 	Serialize<Uint32>::serialize( m_NumIntervals, bufferPointer );
128 	// write the used buffer size
129 	Serialize<Uint32>::serialize( bufferSize, bufferPointer );
130 	// write the Intervals
131 	Serialize<Uint32>::serialize( bufferSize,
132 	                              m_Intervals,
133 	                              bufferPointer );
134 
135 	SERIALIZE_TAG( bufferPointer );
136 	END_SERIALIZED_SIZE_CHECK( bufferPointer, WeightedRandom );
137 }
138 
139 /**********************************************************/
140 
deserialize(Uint8 * & bufferPointer)141 void WeightedRandom::deserialize( Uint8*& bufferPointer )
142 {
143 	Uint32 bufferSize,
144 	       oldNumIntervals = m_NumIntervals;
145 
146 	Random::deserialize( bufferPointer );
147 
148 	// deserialize the number of intervals
149 	Serialize<Uint32>::deserialize( bufferPointer, m_NumIntervals );
150 	// deserialize the used buffer size
151 	Serialize<Uint32>::deserialize( bufferPointer, bufferSize );
152 	// create the interval size, if necessary
153 	if( bufferSize > 0 ) {
154 		if( bufferSize != oldNumIntervals ) {
155 			delete [] m_Intervals;
156 			ASSERT( NULL != (m_Intervals = NEW Uint32 [bufferSize]),
157 			        "WeightedRandom::deserialize: could not create "
158 			        "interval array of size %d\n", bufferSize );
159 			m_NumIntervals = bufferSize;
160 		}
161 		Serialize<Uint32>::deserialize( bufferSize,
162 		                                bufferPointer,
163 		                                m_Intervals );
164 	} else {
165 		delete [] m_Intervals;
166 		m_Intervals    = NULL;
167 		m_NumIntervals = 0;
168 	}
169 
170 	DESERIALIZE_TAG( bufferPointer );
171 }
172 
173 /**********************************************************/
174