Libbarrett  1.2.4
include/barrett/math/matrix.h
00001 /*
00002  * matrix.h
00003  *
00004  *  Created on: Jan 13, 2010
00005  *      Author: dc
00006  */
00007 
00008 #ifndef BARRETT_MATH_MATRIX_H_
00009 #define BARRETT_MATH_MATRIX_H_
00010 
00011 
00012 #include <iostream>
00013 #include <stdexcept>
00014 
00015 #include <boost/type_traits/is_same.hpp>
00016 #include <boost/mpl/assert.hpp>
00017 #include <boost/mpl/if.hpp>
00018 #include <boost/mpl/or.hpp>
00019 
00020 #include <libconfig.h++>
00021 
00022 #include <Eigen/Core>
00023 #include <Eigen/Array>
00024 #include <gsl/gsl_vector.h>
00025 #include <gsl/gsl_matrix.h>
00026 
00027 #include <barrett/math/traits.h>
00028 
00029 
00030 namespace barrett {
00031 namespace math {
00032 
00033 
00034 template<int R, int C, typename Units = void> class Matrix;
00035 
00036 template<int R, typename Units = void>
00037 struct Vector {
00038         typedef math::Matrix<R,1, Units> type;
00039 };
00040 
00041 
00042 template<int R, int C, typename Units>
00043 class Matrix : public Eigen::Matrix<double, R,C, Eigen::RowMajorBit> {
00044 public:
00045         typedef Eigen::Matrix<double, R,C, Eigen::RowMajorBit> Base;
00046         typedef Matrix<R,C, Units> type;
00047 
00048         typedef typename boost::mpl::if_c<
00049                 Base::IsVectorAtCompileTime,
00050                 gsl_vector,
00051                 gsl_matrix
00052         >::type gsl_type;
00053 
00054         // TODO(dc): disable SIZE somehow for dynamic Matrices?
00055         static const size_t SIZE = R*C;  
00056 
00063         typedef Matrix<R,C> unitless_type;
00064 
00065 
00066         // Duplicate the non-inherited parts of Eigen's interface.
00067 //      Matrix();
00068 //      explicit Matrix(int dim);
00069 //      Matrix(int r, int c);
00070         Matrix(double x, double y);
00071         Matrix(double x, double y, double z);
00072         Matrix(double x, double y, double z, double w);
00073         explicit Matrix(const double* data);
00074         template<typename OtherDerived>
00075         Matrix(const Eigen::MatrixBase<OtherDerived>& other);
00076 
00077 //      EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Matrix);
00078         using Base::operator=;
00079 
00080         // the default operator= does it wrong.
00081         inline Matrix& operator=(const Matrix& other) {
00082                 if (this != &other) {
00083                         // GSL stuff doen't need to be altered
00084                         this->Base::operator=(other);
00085                 }
00086                 return *this;
00087         }
00088 
00089         // make sure units match
00090         template<int OtherR, int OtherC, typename OtherUnits>
00091         inline Matrix<R,C, Units>& operator=(const Matrix<OtherR,OtherC, OtherUnits>& other) {
00092                 BOOST_MPL_ASSERT((      boost::mpl::or_<
00093                                                                 boost::is_same<Units,   void>,
00094                                                                 boost::is_same<void,    OtherUnits>,
00095                                                                 boost::is_same<Units,   OtherUnits>
00096                                                         > ));
00097 
00098                 // GSL stuff doen't need to be altered
00099                 this->Base::operator=(other);
00100                 return *this;
00101         }
00102 
00103 
00104         template<typename OtherDerived>
00105         explicit Matrix(const Eigen::RotationBase<OtherDerived,Base::ColsAtCompileTime>& r);
00106 //      template<typename OtherDerived>
00107 //      Matrix& operator=(const Eigen::RotationBase<OtherDerived,Base::ColsAtCompileTime>& r);
00108 
00109         // Additional ctors
00110 
00117         explicit Matrix(double d = 0.0);
00118         explicit Matrix(int r, double d = 0.0);
00119         Matrix(int r, int c, double d = 0.0);
00120         explicit Matrix(const gsl_type* gslType);
00121         Matrix(const libconfig::Setting& setting);  // deliberately non-explicit
00122         Matrix(const Matrix& a);  // TODO(dc): make sure units match in a copy construction
00123         ~Matrix();
00124 
00125         // TODO(dc): add a ctor that doesn't initialize the data?
00126 
00127         // TODO(dc): How does this need to change to support dynamically sized Matrices?
00128         static size_t serializedLength();
00129         void serialize(char* dest) const;
00130         static Matrix<R,C, Units> unserialize(char* source);
00131 
00132         void copyTo(gsl_type* gslType) const throw(std::logic_error);
00133         void copyFrom(const gsl_type* gslType) throw(std::logic_error);
00134 
00135         void copyFrom(const libconfig::Setting& setting);
00136 
00137         gsl_type* asGslType();
00138         const gsl_type* asGslType() const;
00139 
00140 protected:
00141         void resizeIfDynamic(int r, int c = 1);
00142 
00143         void initGslType(gsl_vector* g);
00144         void initGslType(gsl_matrix* g);
00145 
00146         void resizeToMatchIfDynamic(const gsl_vector* g);
00147         void resizeToMatchIfDynamic(const gsl_matrix* g);
00148 
00149         void checkSize(const gsl_vector* g) const;
00150         void checkSize(const gsl_matrix* g) const;
00151 
00152         void copyToHelper(gsl_vector* g) const;
00153         void copyToHelper(gsl_matrix* g) const;
00154 
00155         void copyFromHelper(const gsl_vector* g);
00156         void copyFromHelper(const gsl_matrix* g);
00157 
00158         gsl_type gsl;
00159 };
00160 
00161 
00162 template<int R, int C, typename Units>
00163 std::ostream& operator<< (std::ostream& os, const Matrix<R,C, Units>& a);
00164 
00165 
00166 template<typename TraitsDerived> struct Traits<Eigen::MatrixBase<TraitsDerived> > {
00167         typedef Eigen::MatrixBase<TraitsDerived> MatrixBaseType;
00168         typedef typename MatrixBaseType::ConstantReturnType ConstantReturnType;
00169 
00170 
00171         static const bool IsDynamic = (MatrixBaseType::RowsAtCompileTime == Eigen::Dynamic  ||  MatrixBaseType::ColsAtCompileTime == Eigen::Dynamic);
00172         static const bool RequiresAlignment = !IsDynamic;
00173 
00174 
00175         static const ConstantReturnType zero() {
00176                 return MatrixBaseType::Zero();
00177         }
00178 
00179         static const ConstantReturnType zero(int r) {
00180                 return MatrixBaseType::Zero(r);
00181         }
00182 
00183         static const ConstantReturnType zero(int r, int c) {
00184                 return MatrixBaseType::Zero(r,c);
00185         }
00186 
00187         template<typename Derived>
00188         static void zero(Eigen::MatrixBase<Derived>& t) {
00189                 t.setZero();
00190         }
00191 
00192         // matrix-matrix
00193         template<typename LDerived, typename RDerived> static
00194         const Eigen::CwiseBinaryOp<
00195                 Eigen::ei_scalar_sum_op<
00196                         typename Eigen::ei_traits<LDerived>::Scalar>,
00197                 LDerived,
00198                 RDerived
00199         >
00200         add(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) {
00201                 return l + r;
00202         }
00203 
00204         template<typename LDerived, typename RDerived> static
00205         const Eigen::CwiseBinaryOp<
00206                 Eigen::ei_scalar_difference_op<
00207                         typename Eigen::ei_traits<LDerived>::Scalar>,
00208                 LDerived,
00209                 RDerived
00210         >
00211         sub(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) {
00212                 return l - r;
00213         }
00214 
00215         template<typename LDerived, typename RDerived> static
00216         Eigen::CwiseBinaryOp<
00217                 Eigen::ei_scalar_product_op<
00218                         typename Eigen::ei_scalar_product_traits<
00219                                 typename Eigen::ei_traits<LDerived>::Scalar,
00220                                 typename Eigen::ei_traits<RDerived>::Scalar
00221                                 >::ReturnType
00222                 >,
00223                 LDerived,
00224                 RDerived
00225         >
00226         mult(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) {
00227                 return l.cwise() * r;
00228         }
00229 
00230         template<typename LDerived, typename RDerived> static
00231         Eigen::CwiseBinaryOp<
00232                 Eigen::ei_scalar_quotient_op<typename Eigen::ei_traits<LDerived>::Scalar>,
00233                 LDerived,
00234                 RDerived
00235         >
00236         div(const Eigen::MatrixBase<LDerived>& l, const Eigen::MatrixBase<RDerived>& r) {
00237                 return l.cwise() / r;
00238         }
00239 
00240 
00241         // matrix-scalar
00242         template<typename Derived> static
00243         const Eigen::CwiseUnaryOp<
00244                 Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Derived>::Scalar>,
00245                 Derived
00246         >
00247         add(const Eigen::MatrixBase<Derived>& l, double r) {
00248                 return l.cwise() + r;
00249         }
00250 
00251         template<typename Derived> static
00252         const Eigen::CwiseUnaryOp<
00253                 Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Derived>::Scalar>,
00254                 Derived
00255         >
00256         add(double l, const Eigen::MatrixBase<Derived>& r) {
00257                 return l + r.cwise();
00258         }
00259 
00260         template<typename Derived> static
00261         const Eigen::CwiseUnaryOp<
00262                 Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Derived>::Scalar>,
00263                 Derived
00264         >
00265         sub(const Eigen::MatrixBase<Derived>& l, double r) {
00266                 return l.cwise() - r;
00267         }
00268 
00269         template<typename Derived> static
00270         const Eigen::CwiseUnaryOp<
00271                 Eigen::ei_scalar_opposite_op<typename Eigen::ei_traits<Derived>::Scalar>,
00272                 Derived
00273         >
00274         neg(const Eigen::MatrixBase<Derived>& t) {
00275                 return -t;
00276         }
00277 
00278         template<typename Derived> static
00279 // TODO(dc): this method returns random (uninitialized? deallocated?) values when it has the commented-out return type. i don't know why.
00280 //      const Eigen::CwiseUnaryOp<
00281 //              Eigen::ei_scalar_add_op<typename Eigen::ei_traits<Eigen::CwiseUnaryOp<
00282 //                      Eigen::ei_scalar_opposite_op<typename Eigen::ei_traits<Derived>::Scalar>,
00283 //                      Derived
00284 //              > >::Scalar>,
00285 //              Eigen::CwiseUnaryOp<
00286 //                      Eigen::ei_scalar_opposite_op<typename Eigen::ei_traits<Derived>::Scalar>,
00287 //                      Derived
00288 //              >
00289 //      >
00290         const typename MatrixBaseType::PlainMatrixType
00291         sub(double l, const Eigen::MatrixBase<Derived>& r) {
00292                 return l + (-r).cwise();
00293         }
00294 
00295         template<typename Derived> static
00296         const Eigen::CwiseUnaryOp<
00297                 Eigen::ei_scalar_multiple_op<typename Eigen::ei_traits<Derived>::Scalar>,
00298                 Derived
00299         >
00300         mult(const Eigen::MatrixBase<Derived>& l, double r) {
00301                 return l * r;
00302         }
00303 
00304         template<typename Derived> static
00305         const Eigen::CwiseUnaryOp<
00306                 Eigen::ei_scalar_multiple_op<typename Eigen::ei_traits<Derived>::Scalar>,
00307                 Derived
00308         >
00309         mult(double l, const Eigen::MatrixBase<Derived>& r) {
00310                 return l * r;
00311         }
00312 
00313         template<typename Derived> static
00314         const Eigen::CwiseUnaryOp<
00315                 Eigen::ei_scalar_quotient1_op<typename Eigen::ei_traits<Derived>::Scalar>,
00316                 Derived
00317         >
00318         div(const Eigen::MatrixBase<Derived>& l, double r) {
00319                 return l / r;
00320         }
00321 
00322         template<typename Derived> static
00323 // TODO(dc): this method returns random (uninitialized? deallocated?) values when it has the commented-out return type. i don't know why.
00324 //      const Eigen::CwiseUnaryOp<
00325 //              Eigen::ei_scalar_multiple_op<typename Eigen::ei_traits<Eigen::CwiseUnaryOp<
00326 //                      Eigen::ei_scalar_inverse_op<typename Eigen::ei_traits<Derived>::Scalar>,
00327 //                      Derived
00328 //              > >::Scalar>,
00329 //              Eigen::CwiseUnaryOp<
00330 //                      Eigen::ei_scalar_inverse_op<typename Eigen::ei_traits<Derived>::Scalar>,
00331 //                      Derived
00332 //              >
00333 //      >
00334         const typename MatrixBaseType::PlainMatrixType
00335         div(double l, const Eigen::MatrixBase<Derived>& r) {
00336                 return l * r.cwise().inverse();
00337         }
00338 };
00339 
00340 
00341 template<int R, int C, typename Units> struct Traits<Matrix<R,C, Units> > :
00342                 public Traits<Eigen::MatrixBase<typename Matrix<R,C, Units>::Base> > {
00343         typedef typename Matrix<R,C, Units>::unitless_type unitless_type;
00344 };
00345 
00346 
00347 }
00348 }
00349 
00350 
00351 // include template definitions
00352 #include <barrett/math/detail/matrix-inl.h>
00353 
00354 
00355 #endif /* BARRETT_MATH_MATRIX_H_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Defines