00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00030
00031
00032 #ifndef _TDEPENDENTVALUES_H_
00033 #define _TDEPENDENTVALUES_H_
00034
00035 #include <assert.h>
00036
00037 namespace mbo
00038 {
00039
00047 template< typename _Ty
00048 , size_t _Count
00049 , _Ty _Min
00050 , _Ty _Max
00051 , _Ty _Step
00052 >
00053 class TDependentValues
00054 {
00055 public:
00056
00057 typedef _Ty ValueType;
00058 typedef _Ty ValueArray[_Count];
00059
00062 TDependentValues()
00063 : m_bUpdate(false)
00064 , m_bFixup(true)
00065 {
00066 SetEqual();
00067 }
00068
00072 const ValueType & operator [] (size_t nIndex) const
00073 {
00074 assert(nIndex < _Count);
00075 return m_vtValues[nIndex];
00076 }
00077
00081 ValueType GetValue(size_t nIndex) const
00082 {
00083 assert(nIndex < _Count);
00084 return m_vtValues[nIndex];
00085 }
00086
00089 ValueType GetSum() const
00090 {
00091 ValueType sum(0);
00092
00093 for(size_t nPos = 0; nPos < _Count; ++nPos)
00094 {
00095 sum += m_vtValues[nPos];
00096 }
00097 return sum;
00098 }
00099
00105 bool GetValuesOk() const
00106 {
00107 ValueType sum(0);
00108
00109 for(size_t nPos = 0; nPos < _Count; ++nPos)
00110 {
00111 if (m_vtValues[nPos] < _Min)
00112 {
00113 return false;
00114 }
00115 sum += m_vtValues[nPos];
00116 }
00117 return sum == _Max;
00118 }
00119
00123 void SetEqual()
00124 {
00125 if (!m_bUpdate)
00126 {
00127 m_bUpdate = true;
00128
00129
00130 for(size_t nPos = 0; nPos < _Count; ++nPos)
00131 {
00132 m_vtValues[nPos] = _Max / _Count;
00133 }
00134
00135 FixupSum();
00136
00137
00138 DoUpdateValues(-1);
00139
00140 m_bUpdate = false;
00141 }
00142 }
00143
00149 void SetAllValues(const ValueArray * pvtValues)
00150 {
00151 for(size_t nPos = 0; nPos < _Count; ++nPos)
00152 {
00153 m_vtValues[nPos] = (*pvtValues)[nPos];
00154 }
00155 FixupSum();
00156 DoUpdateValues(-1);
00157 }
00158
00164 void SetValue(size_t nIndex, ValueType new_val)
00165 {
00166 if (!m_bUpdate)
00167 {
00168 m_bUpdate = true;
00169
00170 if (!m_bFixup)
00171 {
00172 m_vtValues[nIndex] = new_val;
00173 DoUpdateValues(nIndex);
00174 }
00175
00176 else if (m_vtValues[nIndex] != new_val)
00177 {
00178
00179 if (new_val >= _Max)
00180 {
00181 for(size_t nPos = 0; nPos < _Count; ++nPos)
00182 {
00183 m_vtValues[nPos] = nPos == nIndex ? _Max : _Min;
00184 }
00185 }
00186 else
00187 {
00188
00189 ValueType count_min_one = _Count - 1;
00190 ValueType diff_val = _Step * (new_val - m_vtValues[nIndex]) / count_min_one;
00191 ValueType miss_val = 0;
00192 ValueType max_val = _Min;
00193 size_t nIndexMax = 0;
00194
00195 for(size_t nPos = 0; nPos < _Count; ++nPos)
00196 {
00197 if (nPos == nIndex)
00198 {
00199 m_vtValues[nPos] += diff_val * count_min_one;
00200 m_vtValues[nPos] = min(m_vtValues[nPos], _Max);
00201 }
00202 else
00203 {
00204 m_vtValues[nPos] -= diff_val;
00205 }
00206
00207 if (m_vtValues[nPos] < _Min)
00208 {
00209 miss_val += _Min - m_vtValues[nPos];
00210 m_vtValues[nPos] = _Min;
00211 }
00212 else if (m_vtValues[nPos] >= max_val)
00213 {
00214 nIndexMax = nPos;
00215 max_val = m_vtValues[nPos];
00216 }
00217 }
00218
00219 if (miss_val)
00220 {
00221 m_vtValues[nIndexMax] -= miss_val;
00222 }
00223
00224 FixupSum();
00225 }
00226
00227 DoUpdateValues(nIndex);
00228 }
00229
00230 m_bUpdate = false;
00231 }
00232 }
00233
00234 protected:
00235
00239 virtual void DoUpdateValues(size_t nIndex)
00240 {
00241
00242 }
00243
00246 virtual void SetAutoFixup(bool bAutoFixup)
00247 {
00248 m_bFixup = bAutoFixup;
00249 if (m_bFixup)
00250 {
00251 FixupSum();
00252 DoUpdateValues(-1);
00253 }
00254 }
00255
00258 virtual bool GetAutoFixup() const
00259 {
00260 return m_bFixup;
00261 }
00262
00263 private:
00264
00270 void FixupSum()
00271 {
00272 if (!m_bFixup)
00273 {
00274 return;
00275 }
00276
00277 ValueType sum = GetSum();
00278 size_t nPos;
00279
00280 while (sum != _Max)
00281 {
00282 for(nPos = 0; sum < _Max && nPos < _Count; ++nPos)
00283 {
00284 if (m_vtValues[nPos] + _Step <= _Max)
00285 {
00286 m_vtValues[nPos] += _Step;
00287 sum += _Step;
00288 }
00289 }
00290 for(nPos = 0; sum > _Max && nPos < _Count; ++nPos)
00291 {
00292 if (m_vtValues[nPos] - _Step >= _Min)
00293 {
00294 m_vtValues[nPos] -= _Step;
00295 sum -= _Step;
00296 }
00297 }
00298 }
00299 }
00300
00301 bool m_bUpdate;
00302 bool m_bFixup;
00303 ValueArray m_vtValues;
00304 };
00305
00306 };
00307
00308 #endif // _TDEPENDENTVALUES_H_