TDependentValues.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 * Copyright (c) 2001 - 2008 Marcus Boerger.  All rights reserved.
00003 *
00004 * This library is free software; you can redistribute it and/or
00005 * modify it under the terms of the GNU Lesser General Public
00006 * License as published by the Free Software Foundation; either
00007 * version 2.1 of the License, or (at your option) any later version.
00008 *
00009 * This library is distributed in the hope that it will be useful,
00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 * Lesser General Public License for more details.
00013 *
00014 * You should have received a copy of the GNU Lesser General Public
00015 * License along with this library; if not, write to the Free Software
00016 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
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             // Correct the values
00130             for(size_t nPos = 0; nPos < _Count; ++nPos)
00131             {
00132                 m_vtValues[nPos] = _Max / _Count;
00133             }
00134 
00135             FixupSum();
00136 
00137             // now that all values are correct again we can notify
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             // check whether at least one value was changed, diff != 0
00176             else if (m_vtValues[nIndex] != new_val)
00177             {
00178                 // if a new value was set 1000 then we need to set all other to zero
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                     // handle the normal case (and later the case when a value was set to zero)
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         // nothing to do here
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 }; // namespace mbo
00307 
00308 #endif // _TDEPENDENTVALUES_H_

  Hosted on code.google.com  
© Marcus Börger
Generated on Fri Jan 18 21:21:08 2008 for MBO-lib by doxygen 1.5.4