![]() |
Eigen
3.3.3
|
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