Eigen  3.3.3
Homogeneous.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_HOMOGENEOUS_H
00011 #define EIGEN_HOMOGENEOUS_H
00012 
00013 namespace Eigen { 
00014 
00030 namespace internal {
00031 
00032 template<typename MatrixType,int Direction>
00033 struct traits<Homogeneous<MatrixType,Direction> >
00034  : traits<MatrixType>
00035 {
00036   typedef typename traits<MatrixType>::StorageKind StorageKind;
00037   typedef typename ref_selector<MatrixType>::type MatrixTypeNested;
00038   typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
00039   enum {
00040     RowsPlusOne = (MatrixType::RowsAtCompileTime != Dynamic) ?
00041                   int(MatrixType::RowsAtCompileTime) + 1 : Dynamic,
00042     ColsPlusOne = (MatrixType::ColsAtCompileTime != Dynamic) ?
00043                   int(MatrixType::ColsAtCompileTime) + 1 : Dynamic,
00044     RowsAtCompileTime = Direction==Vertical  ?  RowsPlusOne : MatrixType::RowsAtCompileTime,
00045     ColsAtCompileTime = Direction==Horizontal ? ColsPlusOne : MatrixType::ColsAtCompileTime,
00046     MaxRowsAtCompileTime = RowsAtCompileTime,
00047     MaxColsAtCompileTime = ColsAtCompileTime,
00048     TmpFlags = _MatrixTypeNested::Flags & HereditaryBits,
00049     Flags = ColsAtCompileTime==1 ? (TmpFlags & ~RowMajorBit)
00050           : RowsAtCompileTime==1 ? (TmpFlags | RowMajorBit)
00051           : TmpFlags
00052   };
00053 };
00054 
00055 template<typename MatrixType,typename Lhs> struct homogeneous_left_product_impl;
00056 template<typename MatrixType,typename Rhs> struct homogeneous_right_product_impl;
00057 
00058 } // end namespace internal
00059 
00060 template<typename MatrixType,int _Direction> class Homogeneous
00061   : public MatrixBase<Homogeneous<MatrixType,_Direction> >, internal::no_assignment_operator
00062 {
00063   public:
00064 
00065     typedef MatrixType NestedExpression;
00066     enum { Direction = _Direction };
00067 
00068     typedef MatrixBase<Homogeneous> Base;
00069     EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
00070 
00071     EIGEN_DEVICE_FUNC explicit inline Homogeneous(const MatrixType& matrix)
00072       : m_matrix(matrix)
00073     {}
00074 
00075     EIGEN_DEVICE_FUNC inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical   ? 1 : 0); }
00076     EIGEN_DEVICE_FUNC inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
00077     
00078     EIGEN_DEVICE_FUNC const NestedExpression& nestedExpression() const { return m_matrix; }
00079 
00080     template<typename Rhs>
00081     EIGEN_DEVICE_FUNC inline const Product<Homogeneous,Rhs>
00082     operator* (const MatrixBase<Rhs>& rhs) const
00083     {
00084       eigen_assert(int(Direction)==Horizontal);
00085       return Product<Homogeneous,Rhs>(*this,rhs.derived());
00086     }
00087 
00088     template<typename Lhs> friend
00089     EIGEN_DEVICE_FUNC inline const Product<Lhs,Homogeneous>
00090     operator* (const MatrixBase<Lhs>& lhs, const Homogeneous& rhs)
00091     {
00092       eigen_assert(int(Direction)==Vertical);
00093       return Product<Lhs,Homogeneous>(lhs.derived(),rhs);
00094     }
00095 
00096     template<typename Scalar, int Dim, int Mode, int Options> friend
00097     EIGEN_DEVICE_FUNC inline const Product<Transform<Scalar,Dim,Mode,Options>, Homogeneous >
00098     operator* (const Transform<Scalar,Dim,Mode,Options>& lhs, const Homogeneous& rhs)
00099     {
00100       eigen_assert(int(Direction)==Vertical);
00101       return Product<Transform<Scalar,Dim,Mode,Options>, Homogeneous>(lhs,rhs);
00102     }
00103 
00104     template<typename Func>
00105     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::result_of<Func(Scalar,Scalar)>::type
00106     redux(const Func& func) const
00107     {
00108       return func(m_matrix.redux(func), Scalar(1));
00109     }
00110 
00111   protected:
00112     typename MatrixType::Nested m_matrix;
00113 };
00114 
00128 template<typename Derived>
00129 EIGEN_DEVICE_FUNC inline typename MatrixBase<Derived>::HomogeneousReturnType
00130 MatrixBase<Derived>::homogeneous() const
00131 {
00132   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
00133   return HomogeneousReturnType(derived());
00134 }
00135 
00146 template<typename ExpressionType, int Direction>
00147 EIGEN_DEVICE_FUNC inline Homogeneous<ExpressionType,Direction>
00148 VectorwiseOp<ExpressionType,Direction>::homogeneous() const
00149 {
00150   return HomogeneousReturnType(_expression());
00151 }
00152 
00170 template<typename Derived>
00171 EIGEN_DEVICE_FUNC inline const typename MatrixBase<Derived>::HNormalizedReturnType
00172 MatrixBase<Derived>::hnormalized() const
00173 {
00174   EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
00175   return ConstStartMinusOne(derived(),0,0,
00176     ColsAtCompileTime==1?size()-1:1,
00177     ColsAtCompileTime==1?1:size()-1) / coeff(size()-1);
00178 }
00179 
00194 template<typename ExpressionType, int Direction>
00195 EIGEN_DEVICE_FUNC inline const typename VectorwiseOp<ExpressionType,Direction>::HNormalizedReturnType
00196 VectorwiseOp<ExpressionType,Direction>::hnormalized() const
00197 {
00198   return HNormalized_Block(_expression(),0,0,
00199       Direction==Vertical   ? _expression().rows()-1 : _expression().rows(),
00200       Direction==Horizontal ? _expression().cols()-1 : _expression().cols()).cwiseQuotient(
00201       Replicate<HNormalized_Factors,
00202                 Direction==Vertical   ? HNormalized_SizeMinusOne : 1,
00203                 Direction==Horizontal ? HNormalized_SizeMinusOne : 1>
00204         (HNormalized_Factors(_expression(),
00205           Direction==Vertical    ? _expression().rows()-1:0,
00206           Direction==Horizontal  ? _expression().cols()-1:0,
00207           Direction==Vertical    ? 1 : _expression().rows(),
00208           Direction==Horizontal  ? 1 : _expression().cols()),
00209          Direction==Vertical   ? _expression().rows()-1 : 1,
00210          Direction==Horizontal ? _expression().cols()-1 : 1));
00211 }
00212 
00213 namespace internal {
00214 
00215 template<typename MatrixOrTransformType>
00216 struct take_matrix_for_product
00217 {
00218   typedef MatrixOrTransformType type;
00219   EIGEN_DEVICE_FUNC static const type& run(const type &x) { return x; }
00220 };
00221 
00222 template<typename Scalar, int Dim, int Mode,int Options>
00223 struct take_matrix_for_product<Transform<Scalar, Dim, Mode, Options> >
00224 {
00225   typedef Transform<Scalar, Dim, Mode, Options> TransformType;
00226   typedef typename internal::add_const<typename TransformType::ConstAffinePart>::type type;
00227   EIGEN_DEVICE_FUNC static type run (const TransformType& x) { return x.affine(); }
00228 };
00229 
00230 template<typename Scalar, int Dim, int Options>
00231 struct take_matrix_for_product<Transform<Scalar, Dim, Projective, Options> >
00232 {
00233   typedef Transform<Scalar, Dim, Projective, Options> TransformType;
00234   typedef typename TransformType::MatrixType type;
00235   EIGEN_DEVICE_FUNC static const type& run (const TransformType& x) { return x.matrix(); }
00236 };
00237 
00238 template<typename MatrixType,typename Lhs>
00239 struct traits<homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs> >
00240 {
00241   typedef typename take_matrix_for_product<Lhs>::type LhsMatrixType;
00242   typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
00243   typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
00244   typedef typename make_proper_matrix_type<
00245                  typename traits<MatrixTypeCleaned>::Scalar,
00246                  LhsMatrixTypeCleaned::RowsAtCompileTime,
00247                  MatrixTypeCleaned::ColsAtCompileTime,
00248                  MatrixTypeCleaned::PlainObject::Options,
00249                  LhsMatrixTypeCleaned::MaxRowsAtCompileTime,
00250                  MatrixTypeCleaned::MaxColsAtCompileTime>::type ReturnType;
00251 };
00252 
00253 template<typename MatrixType,typename Lhs>
00254 struct homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs>
00255   : public ReturnByValue<homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs> >
00256 {
00257   typedef typename traits<homogeneous_left_product_impl>::LhsMatrixType LhsMatrixType;
00258   typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
00259   typedef typename remove_all<typename LhsMatrixTypeCleaned::Nested>::type LhsMatrixTypeNested;
00260   EIGEN_DEVICE_FUNC homogeneous_left_product_impl(const Lhs& lhs, const MatrixType& rhs)
00261     : m_lhs(take_matrix_for_product<Lhs>::run(lhs)),
00262       m_rhs(rhs)
00263   {}
00264 
00265   EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
00266   EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); }
00267 
00268   template<typename Dest> EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const
00269   {
00270     // FIXME investigate how to allow lazy evaluation of this product when possible
00271     dst = Block<const LhsMatrixTypeNested,
00272               LhsMatrixTypeNested::RowsAtCompileTime,
00273               LhsMatrixTypeNested::ColsAtCompileTime==Dynamic?Dynamic:LhsMatrixTypeNested::ColsAtCompileTime-1>
00274             (m_lhs,0,0,m_lhs.rows(),m_lhs.cols()-1) * m_rhs;
00275     dst += m_lhs.col(m_lhs.cols()-1).rowwise()
00276             .template replicate<MatrixType::ColsAtCompileTime>(m_rhs.cols());
00277   }
00278 
00279   typename LhsMatrixTypeCleaned::Nested m_lhs;
00280   typename MatrixType::Nested m_rhs;
00281 };
00282 
00283 template<typename MatrixType,typename Rhs>
00284 struct traits<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
00285 {
00286   typedef typename make_proper_matrix_type<typename traits<MatrixType>::Scalar,
00287                  MatrixType::RowsAtCompileTime,
00288                  Rhs::ColsAtCompileTime,
00289                  MatrixType::PlainObject::Options,
00290                  MatrixType::MaxRowsAtCompileTime,
00291                  Rhs::MaxColsAtCompileTime>::type ReturnType;
00292 };
00293 
00294 template<typename MatrixType,typename Rhs>
00295 struct homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs>
00296   : public ReturnByValue<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
00297 {
00298   typedef typename remove_all<typename Rhs::Nested>::type RhsNested;
00299   EIGEN_DEVICE_FUNC homogeneous_right_product_impl(const MatrixType& lhs, const Rhs& rhs)
00300     : m_lhs(lhs), m_rhs(rhs)
00301   {}
00302 
00303   EIGEN_DEVICE_FUNC inline Index rows() const { return m_lhs.rows(); }
00304   EIGEN_DEVICE_FUNC inline Index cols() const { return m_rhs.cols(); }
00305 
00306   template<typename Dest> EIGEN_DEVICE_FUNC void evalTo(Dest& dst) const
00307   {
00308     // FIXME investigate how to allow lazy evaluation of this product when possible
00309     dst = m_lhs * Block<const RhsNested,
00310                         RhsNested::RowsAtCompileTime==Dynamic?Dynamic:RhsNested::RowsAtCompileTime-1,
00311                         RhsNested::ColsAtCompileTime>
00312             (m_rhs,0,0,m_rhs.rows()-1,m_rhs.cols());
00313     dst += m_rhs.row(m_rhs.rows()-1).colwise()
00314             .template replicate<MatrixType::RowsAtCompileTime>(m_lhs.rows());
00315   }
00316 
00317   typename MatrixType::Nested m_lhs;
00318   typename Rhs::Nested m_rhs;
00319 };
00320 
00321 template<typename ArgType,int Direction>
00322 struct evaluator_traits<Homogeneous<ArgType,Direction> >
00323 {
00324   typedef typename storage_kind_to_evaluator_kind<typename ArgType::StorageKind>::Kind Kind;
00325   typedef HomogeneousShape Shape;  
00326 };
00327 
00328 template<> struct AssignmentKind<DenseShape,HomogeneousShape> { typedef Dense2Dense Kind; };
00329 
00330 
00331 template<typename ArgType,int Direction>
00332 struct unary_evaluator<Homogeneous<ArgType,Direction>, IndexBased>
00333   : evaluator<typename Homogeneous<ArgType,Direction>::PlainObject >
00334 {
00335   typedef Homogeneous<ArgType,Direction> XprType;
00336   typedef typename XprType::PlainObject PlainObject;
00337   typedef evaluator<PlainObject> Base;
00338 
00339   EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
00340     : Base(), m_temp(op)
00341   {
00342     ::new (static_cast<Base*>(this)) Base(m_temp);
00343   }
00344 
00345 protected:
00346   PlainObject m_temp;
00347 };
00348 
00349 // dense = homogeneous
00350 template< typename DstXprType, typename ArgType, typename Scalar>
00351 struct Assignment<DstXprType, Homogeneous<ArgType,Vertical>, internal::assign_op<Scalar,typename ArgType::Scalar>, Dense2Dense>
00352 {
00353   typedef Homogeneous<ArgType,Vertical> SrcXprType;
00354   EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename ArgType::Scalar> &)
00355   {
00356     Index dstRows = src.rows();
00357     Index dstCols = src.cols();
00358     if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
00359       dst.resize(dstRows, dstCols);
00360 
00361     dst.template topRows<ArgType::RowsAtCompileTime>(src.nestedExpression().rows()) = src.nestedExpression();
00362     dst.row(dst.rows()-1).setOnes();
00363   }
00364 };
00365 
00366 // dense = homogeneous
00367 template< typename DstXprType, typename ArgType, typename Scalar>
00368 struct Assignment<DstXprType, Homogeneous<ArgType,Horizontal>, internal::assign_op<Scalar,typename ArgType::Scalar>, Dense2Dense>
00369 {
00370   typedef Homogeneous<ArgType,Horizontal> SrcXprType;
00371   EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<Scalar,typename ArgType::Scalar> &)
00372   {
00373     Index dstRows = src.rows();
00374     Index dstCols = src.cols();
00375     if((dst.rows()!=dstRows) || (dst.cols()!=dstCols))
00376       dst.resize(dstRows, dstCols);
00377 
00378     dst.template leftCols<ArgType::ColsAtCompileTime>(src.nestedExpression().cols()) = src.nestedExpression();
00379     dst.col(dst.cols()-1).setOnes();
00380   }
00381 };
00382 
00383 template<typename LhsArg, typename Rhs, int ProductTag>
00384 struct generic_product_impl<Homogeneous<LhsArg,Horizontal>, Rhs, HomogeneousShape, DenseShape, ProductTag>
00385 {
00386   template<typename Dest>
00387   EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const Homogeneous<LhsArg,Horizontal>& lhs, const Rhs& rhs)
00388   {
00389     homogeneous_right_product_impl<Homogeneous<LhsArg,Horizontal>, Rhs>(lhs.nestedExpression(), rhs).evalTo(dst);
00390   }
00391 };
00392 
00393 template<typename Lhs,typename Rhs>
00394 struct homogeneous_right_product_refactoring_helper
00395 {
00396   enum {
00397     Dim  = Lhs::ColsAtCompileTime,
00398     Rows = Lhs::RowsAtCompileTime
00399   };
00400   typedef typename Rhs::template ConstNRowsBlockXpr<Dim>::Type          LinearBlockConst;
00401   typedef typename remove_const<LinearBlockConst>::type                 LinearBlock;
00402   typedef typename Rhs::ConstRowXpr                                     ConstantColumn;
00403   typedef Replicate<const ConstantColumn,Rows,1>                        ConstantBlock;
00404   typedef Product<Lhs,LinearBlock,LazyProduct>                          LinearProduct;
00405   typedef CwiseBinaryOp<internal::scalar_sum_op<typename Lhs::Scalar,typename Rhs::Scalar>, const LinearProduct, const ConstantBlock> Xpr;
00406 };
00407 
00408 template<typename Lhs, typename Rhs, int ProductTag>
00409 struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, HomogeneousShape, DenseShape>
00410  : public evaluator<typename homogeneous_right_product_refactoring_helper<typename Lhs::NestedExpression,Rhs>::Xpr>
00411 {
00412   typedef Product<Lhs, Rhs, LazyProduct> XprType;
00413   typedef homogeneous_right_product_refactoring_helper<typename Lhs::NestedExpression,Rhs> helper;
00414   typedef typename helper::ConstantBlock ConstantBlock;
00415   typedef typename helper::Xpr RefactoredXpr;
00416   typedef evaluator<RefactoredXpr> Base;
00417   
00418   EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
00419     : Base(  xpr.lhs().nestedExpression() .lazyProduct(  xpr.rhs().template topRows<helper::Dim>(xpr.lhs().nestedExpression().cols()) )
00420             + ConstantBlock(xpr.rhs().row(xpr.rhs().rows()-1),xpr.lhs().rows(), 1) )
00421   {}
00422 };
00423 
00424 template<typename Lhs, typename RhsArg, int ProductTag>
00425 struct generic_product_impl<Lhs, Homogeneous<RhsArg,Vertical>, DenseShape, HomogeneousShape, ProductTag>
00426 {
00427   template<typename Dest>
00428   EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
00429   {
00430     homogeneous_left_product_impl<Homogeneous<RhsArg,Vertical>, Lhs>(lhs, rhs.nestedExpression()).evalTo(dst);
00431   }
00432 };
00433 
00434 // TODO: the following specialization is to address a regression from 3.2 to 3.3
00435 // In the future, this path should be optimized.
00436 template<typename Lhs, typename RhsArg, int ProductTag>
00437 struct generic_product_impl<Lhs, Homogeneous<RhsArg,Vertical>, TriangularShape, HomogeneousShape, ProductTag>
00438 {
00439   template<typename Dest>
00440   static void evalTo(Dest& dst, const Lhs& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
00441   {
00442     dst.noalias() = lhs * rhs.eval();
00443   }
00444 };
00445 
00446 template<typename Lhs,typename Rhs>
00447 struct homogeneous_left_product_refactoring_helper
00448 {
00449   enum {
00450     Dim = Rhs::RowsAtCompileTime,
00451     Cols = Rhs::ColsAtCompileTime
00452   };
00453   typedef typename Lhs::template ConstNColsBlockXpr<Dim>::Type          LinearBlockConst;
00454   typedef typename remove_const<LinearBlockConst>::type                 LinearBlock;
00455   typedef typename Lhs::ConstColXpr                                     ConstantColumn;
00456   typedef Replicate<const ConstantColumn,1,Cols>                        ConstantBlock;
00457   typedef Product<LinearBlock,Rhs,LazyProduct>                          LinearProduct;
00458   typedef CwiseBinaryOp<internal::scalar_sum_op<typename Lhs::Scalar,typename Rhs::Scalar>, const LinearProduct, const ConstantBlock> Xpr;
00459 };
00460 
00461 template<typename Lhs, typename Rhs, int ProductTag>
00462 struct product_evaluator<Product<Lhs, Rhs, LazyProduct>, ProductTag, DenseShape, HomogeneousShape>
00463  : public evaluator<typename homogeneous_left_product_refactoring_helper<Lhs,typename Rhs::NestedExpression>::Xpr>
00464 {
00465   typedef Product<Lhs, Rhs, LazyProduct> XprType;
00466   typedef homogeneous_left_product_refactoring_helper<Lhs,typename Rhs::NestedExpression> helper;
00467   typedef typename helper::ConstantBlock ConstantBlock;
00468   typedef typename helper::Xpr RefactoredXpr;
00469   typedef evaluator<RefactoredXpr> Base;
00470   
00471   EIGEN_DEVICE_FUNC explicit product_evaluator(const XprType& xpr)
00472     : Base(   xpr.lhs().template leftCols<helper::Dim>(xpr.rhs().nestedExpression().rows()) .lazyProduct( xpr.rhs().nestedExpression() )
00473             + ConstantBlock(xpr.lhs().col(xpr.lhs().cols()-1),1,xpr.rhs().cols()) )
00474   {}
00475 };
00476 
00477 template<typename Scalar, int Dim, int Mode,int Options, typename RhsArg, int ProductTag>
00478 struct generic_product_impl<Transform<Scalar,Dim,Mode,Options>, Homogeneous<RhsArg,Vertical>, DenseShape, HomogeneousShape, ProductTag>
00479 {
00480   typedef Transform<Scalar,Dim,Mode,Options> TransformType;
00481   template<typename Dest>
00482   EIGEN_DEVICE_FUNC static void evalTo(Dest& dst, const TransformType& lhs, const Homogeneous<RhsArg,Vertical>& rhs)
00483   {
00484     homogeneous_left_product_impl<Homogeneous<RhsArg,Vertical>, TransformType>(lhs, rhs.nestedExpression()).evalTo(dst);
00485   }
00486 };
00487 
00488 template<typename ExpressionType, int Side, bool Transposed>
00489 struct permutation_matrix_product<ExpressionType, Side, Transposed, HomogeneousShape>
00490   : public permutation_matrix_product<ExpressionType, Side, Transposed, DenseShape>
00491 {};
00492 
00493 } // end namespace internal
00494 
00495 } // end namespace Eigen
00496 
00497 #endif // EIGEN_HOMOGENEOUS_H
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends