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