00001 #ifndef AFL_VALUET_H
00002 #define AFL_VALUET_H
00003
00004 #include "exc/invalidargumentexception.h"
00005 #include "exc/outofboundsexception.h"
00006 #include "ddf/geometry.h"
00007 #include "ddf/ddf.h"
00008 #include <vector>
00009 #include <sstream>
00010
00011 namespace afl
00012 {
00018 template <typename T>
00019 class ValueT
00020 {
00021 private:
00022 template <typename R>
00023 class ValueRow
00024 {
00025 friend class ValueT<R>;
00026
00027 public:
00033 ValueRow(ValueT<R>* parent, size_t row)
00034 : _parent(parent), _cparent(NULL), _r(row)
00035 {
00036 if (_r > _parent->getRows())
00037 throw exc::OutOfBoundsException("value row is beyond size of value");
00038 }
00039
00045 ValueRow(const ValueT<R>* parent, size_t row)
00046 : _parent(NULL), _cparent(parent), _r(row)
00047 {
00048 if (_r > _cparent->getRows())
00049 throw exc::OutOfBoundsException("value row is beyond size of value");
00050 }
00051
00057 operator const T&() const
00058 {
00059 if (_parent->_c != 1)
00060 throw exc::InvalidArgumentException("Only a Nx1 value can be dereferenced as a vector");
00061
00062 return _parent->_v[_r];
00063 }
00064
00070 operator T&()
00071 {
00072 if (_parent->_c != 1)
00073 throw exc::InvalidArgumentException("Only a Nx1 value can be dereferenced as a vector");
00074
00075 return _parent->_v[_r];
00076 }
00077
00086 const T& operator[](size_t c) const
00087 {
00088 if (c >= _cparent->_c)
00089 throw exc::OutOfBoundsException("value out of bounds");
00090
00091 return _cparent->_v[_r * _cparent->_c + c];
00092 }
00093
00102 T& operator[](size_t c)
00103 {
00104 if (c >= _parent->_c)
00105 {
00106 std::ostringstream oss;
00107 oss << "value out of bounds: There are " << _parent->_c << " columns, and you asked for column #" << c ;
00108 throw exc::OutOfBoundsException(oss.str());
00109 }
00110 return _parent->_v[_r * _parent->_c + c];
00111 }
00112
00113 private:
00114 ValueT<R>* _parent;
00115 const ValueT<R>* _cparent;
00116 size_t _r;
00117
00118 };
00119
00120 friend class ValueRow<T>;
00121
00123 public:
00124
00128 ValueT( )
00129 : _v(), _c(0)
00130 {
00131 }
00132
00137 ValueT( const T& d )
00138 : _v(), _c(1)
00139 {
00140 _v.push_back(d);
00141 }
00142
00148 ValueT( const T& x, const T& y )
00149 : _v(), _c(1)
00150 {
00151 _v.push_back(x);
00152 _v.push_back(y);
00153 }
00154
00161 ValueT( const T& x, const T& y, const T& z )
00162 : _v(), _c(1)
00163 {
00164 _v.push_back(x);
00165 _v.push_back(y);
00166 _v.push_back(z);
00167 }
00168
00176 ValueT( const T& x, const T& y, const T& z, const T& t )
00177 : _v(), _c(1)
00178 {
00179 _v.push_back(x);
00180 _v.push_back(y);
00181 _v.push_back(z);
00182 _v.push_back(t);
00183 }
00184
00189 explicit ValueT( const ddf::Geometry* geom );
00190
00195 explicit ValueT( const ddf::Geometry& geom );
00196
00200 ddf::Geometry getGeometry( ) const
00201 {
00202 return ddf::Geometry(_v.size()/_c, _c);
00203 }
00204
00208 ~ValueT( ) { }
00209
00214 ValueT( const ValueT<T>& c ) : _v(c._v), _c(c._c) { }
00215
00221 ValueT<T>& operator=( const ValueT<T>& c)
00222 {
00223 if (&c == this)
00224 return *this;
00225
00226 _v = c._v;
00227 _c = c._c;
00228 return *this;
00229 }
00230
00234 size_t getRows( ) const { return _v.size() / _c; }
00235
00239 size_t getColumns( ) const { return _c; }
00240
00248 const T& at( size_t r, size_t c = 0 ) const
00249 {
00250 if ( c > _c || r*_c+c > _v.size())
00251 throw exc::OutOfBoundsException("at() is out of bounds");
00252
00253 return _v[r*_c+c];
00254 }
00255
00263 T& at( size_t r, size_t c = 0 )
00264 {
00265 if ( c > _c || r*_c+c > _v.size())
00266 throw exc::OutOfBoundsException("at() is out of bounds");
00267
00268 return _v[r*_c+c];
00269 }
00270
00277 const ValueRow<T> operator[](size_t r) const { return ValueRow<T>(this, r); }
00278
00285 ValueRow<T> operator[](size_t r) { return ValueRow<T>(this, r); }
00286
00292 operator const T&() const
00293 {
00294
00295
00296 if (_v.size() != 1)
00297 {
00298 std::ostringstream oss;
00299 oss << _v.size();
00300
00301
00302 throw exc::InvalidArgumentException("Only a 1x1 value can be dereferenced as a scalar. The value has " + oss.str() + " elements");
00303 }
00304
00305 return _v[0];
00306 }
00307
00313 operator T&()
00314 {
00315
00316
00317 if (_v.size() != 1)
00318 {
00319 std::ostringstream oss;
00320 oss << _v.size();
00321
00322
00323 throw exc::InvalidArgumentException("Only a 1x1 value can be dereferenced as a scalar. The value has " + oss.str() + " elements");
00324 }
00325
00326 return _v[0];
00327 }
00328
00334 std::string geomString( ) const
00335 {
00336 if (_c == 3)
00337 return "tensor3D";
00338 if (_c == 2)
00339 return "tensor2D";
00340 size_t rows = _v.size() / _c;
00341 if (rows == 3)
00342 return "vector3D";
00343 if (rows == 2)
00344 return "vector2D";
00345 return "scalar";
00346 }
00347
00354 ValueT<T>& operator+=( const ValueT<T>& v )
00355 {
00356 if (_c != v._c || _v.size() != v._v.size())
00357 throw exc::InvalidArgumentException("can't add values of differing geometries");
00358
00359 for (size_t i = 0 ; i < _v.size() ; ++i)
00360 _v[i] += v._v[i];
00361
00362 return *this;
00363 }
00364
00371 ValueT<T>& operator/=( const data_t& div )
00372 {
00373 for (size_t i = 0 ; i < _v.size() ; ++i)
00374 _v[i] /= div;
00375
00376 return *this;
00377 }
00378
00385 ValueT<T>& operator*=( const data_t& multiplier )
00386 {
00387 for (size_t i = 0 ; i < _v.size() ; ++i)
00388 _v[i] *= multiplier;
00389
00390 return *this;
00391 }
00392
00400 bool operator==( const ValueT<T>& lhs ) const
00401 {
00402 if (_c != lhs._c || _v.size() != lhs._v.size())
00403 return false;
00404
00405 for (size_t i = 0 ; i < _v.size() ; ++i)
00406 if (_v[i] != lhs._v[i])
00407 return false;
00408
00409 return true;
00410 }
00411
00419 bool operator!=( const ValueT<T>& lhs ) const
00420 {
00421 return ! (*this == lhs);
00422 }
00423
00425 protected:
00429 std::vector<T> _v;
00430
00436 size_t _c;
00437 };
00438
00439 }
00440
00441 #endif // AFL_VALUET_H
00442