ICRS Eurobot 2013

Dependencies:   mbed mbed-rtos Servo QEI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Matrix.h Source File

Matrix.h

00001 /*
00002  * Tiny Vector Matrix Library
00003  * Dense Vector Matrix Libary of Tiny size using Expression Templates
00004  *
00005  * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.net>
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * $Id: Matrix.h,v 1.58 2007-06-23 15:58:58 opetzold Exp $
00022  */
00023 
00024 #ifndef TVMET_MATRIX_H
00025 #define TVMET_MATRIX_H
00026 
00027 #include <iterator>                    // reverse_iterator
00028 
00029 #include <tvmet/tvmet.h>
00030 #include <tvmet/TypePromotion.h>
00031 #include <tvmet/CommaInitializer.h>
00032 #include <tvmet/RunTimeError.h>
00033 
00034 #include <tvmet/xpr/Matrix.h>
00035 #include <tvmet/xpr/MatrixRow.h>
00036 #include <tvmet/xpr/MatrixCol.h>
00037 #include <tvmet/xpr/MatrixDiag.h>
00038 
00039 namespace tvmet {
00040 
00041 
00042 /* forwards */
00043 template<class T, std::size_t Rows, std::size_t Cols> class Matrix;
00044 template<class T,
00045      std::size_t RowsBgn, std::size_t RowsEnd,
00046      std::size_t ColsBgn, std::size_t ColsEnd,
00047      std::size_t RowStride, std::size_t ColStride /*=1*/>
00048 class MatrixSliceConstReference; // unused here; for me only
00049 
00050 
00051 /**
00052  * \class MatrixConstReference Matrix.h "tvmet/Matrix.h"
00053  * \brief value iterator for ET
00054  */
00055 template<class T, std::size_t NRows, std::size_t NCols>
00056 class MatrixConstReference
00057   : public TvmetBase < MatrixConstReference<T, NRows, NCols> >
00058 {
00059 public:
00060   typedef T                        value_type;
00061   typedef T*                        pointer;
00062   typedef const T*                    const_pointer;
00063 
00064   /** Dimensions. */
00065   enum {
00066     Rows = NRows,            /**< Number of rows. */
00067     Cols = NCols,            /**< Number of cols. */
00068     Size = Rows * Cols            /**< Complete Size of Matrix. */
00069   };
00070 
00071 public:
00072   /** Complexity counter. */
00073   enum {
00074     ops       = Rows * Cols
00075   };
00076 
00077 private:
00078   MatrixConstReference();
00079   MatrixConstReference& operator=(const MatrixConstReference&);
00080 
00081 public:
00082   /** Constructor. */
00083   explicit MatrixConstReference(const Matrix<T, Rows, Cols>& rhs)
00084     : m_data(rhs.data())
00085   { }
00086 
00087   /** Constructor by a given memory pointer. */
00088   explicit MatrixConstReference(const_pointer data)
00089     : m_data(data)
00090   { }
00091 
00092 public: // access operators
00093   /** access by index. */
00094   value_type operator()(std::size_t i, std::size_t j) const {
00095     TVMET_RT_CONDITION((i < Rows) && (j < Cols), "MatrixConstReference Bounce Violation")
00096     return m_data[i * Cols + j];
00097   }
00098 
00099 public: // debugging Xpr parse tree
00100   void print_xpr(std::ostream& os, std::size_t l=0) const {
00101     os << IndentLevel(l)
00102        << "MatrixConstReference[O=" << ops << "]<"
00103        << "T=" << typeid(value_type).name() << ">,"
00104        << std::endl;
00105   }
00106 
00107 private:
00108   const_pointer _tvmet_restrict             m_data;
00109 };
00110 
00111 
00112 /**
00113  * \class Matrix Matrix.h "tvmet/Matrix.h"
00114  * \brief A tiny matrix class.
00115  *
00116  * The array syntax A[j][j] isn't supported here. The reason is that
00117  * operator[] always takes exactly one parameter, but operator() can
00118  * take any number of parameters (in the case of a rectangular matrix,
00119  * two paramters are needed). Therefore the cleanest way to do it is
00120  * with operator() rather than with operator[]. \see C++ FAQ Lite 13.8
00121  */
00122 template<class T, std::size_t NRows, std::size_t NCols>
00123 class Matrix
00124 {
00125 public:
00126   /** Data type of the tvmet::Matrix. */
00127   typedef T                        value_type;
00128 
00129   /** Reference type of the tvmet::Matrix data elements. */
00130   typedef T&                         reference;
00131 
00132   /** const reference type of the tvmet::Matrix data elements. */
00133   typedef const T&                         const_reference;
00134 
00135   /** STL iterator interface. */
00136   typedef T*                         iterator;
00137 
00138   /** STL const_iterator interface. */
00139   typedef const T*                         const_iterator;
00140 
00141   /** STL reverse iterator interface. */
00142   typedef std::reverse_iterator<iterator>         reverse_iterator;
00143 
00144   /** STL const reverse iterator interface. */
00145   typedef std::reverse_iterator<const_iterator>     const_reverse_iterator;
00146 
00147 public:
00148   /** Dimensions. */
00149   enum {
00150     Rows = NRows,            /**< Number of rows. */
00151     Cols = NCols,            /**< Number of cols. */
00152     Size = Rows * Cols            /**< Complete Size of Matrix. */
00153   };
00154 
00155 public:
00156   /** Complexity counter. */
00157   enum {
00158     ops_assign = Rows * Cols,
00159     ops        = ops_assign,
00160     use_meta   = ops < TVMET_COMPLEXITY_M_ASSIGN_TRIGGER ? true : false
00161   };
00162 
00163 public: // STL  interface
00164   /** STL iterator interface. */
00165   iterator begin() { return m_data; }
00166 
00167   /** STL iterator interface. */
00168   iterator end() { return m_data + Size; }
00169 
00170   /** STL const_iterator interface. */
00171   const_iterator begin() const { return m_data; }
00172 
00173   /** STL const_iterator interface. */
00174   const_iterator end() const { return m_data + Size; }
00175 
00176   /** STL reverse iterator interface reverse begin. */
00177   reverse_iterator rbegin() { return reverse_iterator( end() ); }
00178 
00179   /** STL const reverse iterator interface reverse begin. */
00180   const_reverse_iterator rbegin() const {
00181     return const_reverse_iterator( end() );
00182   }
00183 
00184   /** STL reverse iterator interface reverse end. */
00185   reverse_iterator rend() { return reverse_iterator( begin() ); }
00186 
00187   /** STL const reverse iterator interface reverse end. */
00188   const_reverse_iterator rend() const {
00189     return const_reverse_iterator( begin() );
00190   }
00191 
00192   /** The size of the matrix. */
00193   static std::size_t size() { return Size; }
00194 
00195   /** STL vector max_size() - returns allways rows()*cols(). */
00196   static std::size_t max_size() { return Size; }
00197 
00198   /** STL vector empty() - returns allways false. */
00199   static bool empty() { return false; }
00200 
00201 public:
00202   /** The number of rows of matrix. */
00203   static std::size_t rows() { return Rows; }
00204 
00205   /** The number of columns of matrix. */
00206   static std::size_t cols() { return Cols; }
00207 
00208 public:
00209   /** Default Destructor */
00210   ~Matrix() {
00211 #if defined(TVMET_DYNAMIC_MEMORY)
00212     delete [] m_data;
00213 #endif
00214   }
00215 
00216   /** Default Constructor. The allocated memory region isn't cleared. If you want
00217    a clean use the constructor argument zero. */
00218   explicit Matrix()
00219 #if defined(TVMET_DYNAMIC_MEMORY)
00220     : m_data( new value_type[Size] )
00221 #endif
00222   { }
00223 
00224   /** Copy Constructor, not explicit! */
00225   Matrix(const Matrix& rhs)
00226 #if defined(TVMET_DYNAMIC_MEMORY)
00227     : m_data( new value_type[Size] )
00228 #endif
00229   {
00230     *this = XprMatrix<ConstReference, Rows, Cols>(rhs.const_ref());
00231   }
00232 
00233   /**
00234    * Constructor with STL iterator interface. The data will be copied into the matrix
00235    * self, there isn't any stored reference to the array pointer.
00236    */
00237   template<class InputIterator>
00238   explicit Matrix(InputIterator first, InputIterator last)
00239 #if defined(TVMET_DYNAMIC_MEMORY)
00240     : m_data( new value_type[Size] )
00241 #endif
00242   {
00243     TVMET_RT_CONDITION(static_cast<std::size_t>(std::distance(first, last)) <= Size,
00244                "InputIterator doesn't fits in size" )
00245     std::copy(first, last, m_data);
00246   }
00247 
00248   /**
00249    * Constructor with STL iterator interface. The data will be copied into the matrix
00250    * self, there isn't any stored reference to the array pointer.
00251    */
00252   template<class InputIterator>
00253   explicit Matrix(InputIterator first, std::size_t sz)
00254 #if defined(TVMET_DYNAMIC_MEMORY)
00255     : m_data( new value_type[Size] )
00256 #endif
00257   {
00258     TVMET_RT_CONDITION(sz <= Size, "InputIterator doesn't fits in size" )
00259     std::copy(first, first + sz, m_data);
00260   }
00261 
00262   /** Construct the matrix by value. */
00263   explicit Matrix(value_type rhs)
00264 #if defined(TVMET_DYNAMIC_MEMORY)
00265     : m_data( new value_type[Size] )
00266 #endif
00267   {
00268     typedef XprLiteral<value_type> expr_type;
00269     *this = XprMatrix<expr_type, Rows, Cols>(expr_type(rhs));
00270   }
00271 
00272   /** Construct a matrix by expression. */
00273   template<class E>
00274   explicit Matrix(const XprMatrix<E, Rows, Cols>& e)
00275 #if defined(TVMET_DYNAMIC_MEMORY)
00276     : m_data( new value_type[Size] )
00277 #endif
00278   {
00279     *this = e;
00280   }
00281 
00282   /** assign a value_type on array, this can be used for a single value
00283       or a comma separeted list of values. */
00284   CommaInitializer<Matrix, Size> operator=(value_type rhs) {
00285     return CommaInitializer<Matrix, Size>(*this, rhs);
00286   }
00287 
00288 public: // access operators
00289   value_type* _tvmet_restrict data() { return m_data; }
00290   const value_type* _tvmet_restrict data() const { return m_data; }
00291 
00292 public: // index access operators
00293   value_type& _tvmet_restrict operator()(std::size_t i, std::size_t j) {
00294     // Note: g++-2.95.3 does have problems on typedef reference
00295     TVMET_RT_CONDITION((i < Rows) && (j < Cols), "Matrix Bounce Violation")
00296     return m_data[i * Cols + j];
00297   }
00298 
00299   value_type operator()(std::size_t i, std::size_t j) const {
00300     TVMET_RT_CONDITION((i < Rows) && (j < Cols), "Matrix Bounce Violation")
00301     return m_data[i * Cols + j];
00302   }
00303 
00304 public: // ET interface
00305   typedef MatrixConstReference<T, Rows, Cols>       ConstReference;
00306 
00307   typedef MatrixSliceConstReference<
00308     T,
00309     0, Rows, 0, Cols,
00310     Rows, 1
00311   >                            SliceConstReference;
00312 
00313   /** Return a const Reference of the internal data */
00314   ConstReference const_ref() const { return ConstReference(*this); }
00315 
00316   /**
00317    * Return a sliced const Reference of the internal data.
00318    * \note Doesn't work since isn't implemented, but it is in
00319    * progress. Therefore this is a placeholder. */
00320   ConstReference const_sliceref() const { return SliceConstReference(*this); }
00321 
00322   /** Return the vector as const expression. */
00323   XprMatrix<ConstReference, Rows, Cols> as_expr() const {
00324     return XprMatrix<ConstReference, Rows, Cols>(this->const_ref());
00325   }
00326 
00327 private:
00328   /** Wrapper for meta assign. */
00329   template<class Dest, class Src, class Assign>
00330   static inline
00331   void do_assign(dispatch<true>, Dest& dest, const Src& src, const Assign& assign_fn) {
00332     meta::Matrix<Rows, Cols, 0, 0>::assign(dest, src, assign_fn);
00333   }
00334 
00335   /** Wrapper for loop assign. */
00336   template<class Dest, class Src, class Assign>
00337   static inline
00338   void do_assign(dispatch<false>, Dest& dest, const Src& src, const Assign& assign_fn) {
00339     loop::Matrix<Rows, Cols>::assign(dest, src, assign_fn);
00340   }
00341 
00342 private:
00343   /** assign this to a matrix  of a different type T2 using
00344       the functional assign_fn. */
00345   template<class T2, class Assign>
00346   void assign_to(Matrix<T2, Rows, Cols>& dest, const Assign& assign_fn) const {
00347     do_assign(dispatch<use_meta>(), dest, *this, assign_fn);
00348   }
00349 
00350 public:  // assign operations
00351   /** assign a given matrix of a different type T2 element wise
00352       to this matrix. The operator=(const Matrix&) is compiler
00353       generated. */
00354   template<class T2>
00355   Matrix& operator=(const Matrix<T2, Rows, Cols>& rhs) {
00356     rhs.assign_to(*this, Fcnl_assign<value_type, T2>());
00357     return *this;
00358   }
00359 
00360   /** assign a given XprMatrix element wise to this matrix. */
00361   template <class E>
00362   Matrix& operator=(const XprMatrix<E, Rows, Cols>& rhs) {
00363     rhs.assign_to(*this, Fcnl_assign<value_type, typename E::value_type>());
00364     return *this;
00365   }
00366 
00367 private:
00368   template<class Obj, std::size_t LEN> friend class CommaInitializer;
00369 
00370   /** This is a helper for assigning a comma separated initializer
00371       list. It's equal to Matrix& operator=(value_type) which does
00372       replace it. */
00373   Matrix& assign_value(value_type rhs) {
00374     typedef XprLiteral<value_type>             expr_type;
00375     *this = XprMatrix<expr_type, Rows, Cols>(expr_type(rhs));
00376     return *this;
00377   }
00378 
00379 public: // math operators with scalars
00380   // NOTE: this meaning is clear - element wise ops even if not in ns element_wise
00381   Matrix& operator+=(value_type) TVMET_CXX_ALWAYS_INLINE;
00382   Matrix& operator-=(value_type) TVMET_CXX_ALWAYS_INLINE;
00383   Matrix& operator*=(value_type) TVMET_CXX_ALWAYS_INLINE;
00384   Matrix& operator/=(value_type) TVMET_CXX_ALWAYS_INLINE;
00385 
00386   Matrix& operator%=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
00387   Matrix& operator^=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
00388   Matrix& operator&=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
00389   Matrix& operator|=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
00390   Matrix& operator<<=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
00391   Matrix& operator>>=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
00392 
00393 public: // math operators with matrizes
00394   // NOTE: access using the operators in ns element_wise, since that's what is does
00395   template <class T2> Matrix& M_add_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00396   template <class T2> Matrix& M_sub_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00397   template <class T2> Matrix& M_mul_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00398   template <class T2> Matrix& M_div_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00399   template <class T2> Matrix& M_mod_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00400   template <class T2> Matrix& M_xor_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00401   template <class T2> Matrix& M_and_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00402   template <class T2> Matrix& M_or_eq (const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00403   template <class T2> Matrix& M_shl_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00404   template <class T2> Matrix& M_shr_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00405 
00406 public: // math operators with expressions
00407   // NOTE: access using the operators in ns element_wise, since that's what is does
00408   template <class E> Matrix& M_add_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00409   template <class E> Matrix& M_sub_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00410   template <class E> Matrix& M_mul_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00411   template <class E> Matrix& M_div_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00412   template <class E> Matrix& M_mod_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00413   template <class E> Matrix& M_xor_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00414   template <class E> Matrix& M_and_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00415   template <class E> Matrix& M_or_eq (const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00416   template <class E> Matrix& M_shl_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00417   template <class E> Matrix& M_shr_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00418 
00419 public: // aliased math operators with expressions
00420   template <class T2> Matrix& alias_assign(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00421   template <class T2> Matrix& alias_add_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00422   template <class T2> Matrix& alias_sub_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00423   template <class T2> Matrix& alias_mul_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00424   template <class T2> Matrix& alias_div_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00425 
00426   template <class E> Matrix& alias_assign(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00427   template <class E> Matrix& alias_add_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00428   template <class E> Matrix& alias_sub_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00429   template <class E> Matrix& alias_mul_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00430   template <class E> Matrix& alias_div_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
00431 
00432 public: // io
00433   /** Structure for info printing as Matrix<T, Rows, Cols>. */
00434   struct Info : public TvmetBase<Info> {
00435     std::ostream& print_xpr(std::ostream& os) const {
00436       os << "Matrix<T=" << typeid(value_type).name()
00437      << ", R=" << Rows << ", C=" << Cols << ">";
00438       return os;
00439     }
00440   };
00441 
00442   /** Get an info object of this matrix. */
00443   static Info info() { return Info(); }
00444 
00445   /** Member function for expression level printing. */
00446   std::ostream& print_xpr(std::ostream& os, std::size_t l=0) const;
00447 
00448   /** Member function for printing internal data. */
00449   std::ostream& print_on(std::ostream& os) const;
00450 
00451 private:
00452   /** The data of matrix self. */
00453 #if defined(TVMET_DYNAMIC_MEMORY)
00454   value_type*                        m_data;
00455 #else
00456   value_type                         m_data[Size];
00457 #endif
00458 };
00459 
00460 
00461 } // namespace tvmet
00462 
00463 #include <tvmet/MatrixImpl.h>
00464 #include <tvmet/MatrixFunctions.h>
00465 #include <tvmet/MatrixBinaryFunctions.h>
00466 #include <tvmet/MatrixUnaryFunctions.h>
00467 #include <tvmet/MatrixOperators.h>
00468 #include <tvmet/MatrixEval.h>
00469 #include <tvmet/AliasProxy.h>
00470 
00471 #endif // TVMET_MATRIX_H
00472 
00473 // Local Variables:
00474 // mode:C++
00475 // tab-width:8
00476 // End: