From c6f610093bff10c5a6e4fac94bfed422ba54b39a Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Sun, 5 Jul 2009 11:33:55 +0200 Subject: [PATCH] add a VectorBlock expr as a specialization of Block --- Eigen/Core | 1 + Eigen/src/Core/Block.h | 243 ----------------- Eigen/src/Core/MatrixBase.h | 24 +- Eigen/src/Core/VectorBlock.h | 311 ++++++++++++++++++++++ Eigen/src/Core/util/ForwardDeclarations.h | 1 + Eigen/src/Core/util/XprHelper.h | 2 - doc/examples/class_FixedVectorBlock.cpp | 26 ++ doc/examples/class_VectorBlock.cpp | 26 ++ 8 files changed, 377 insertions(+), 257 deletions(-) create mode 100644 Eigen/src/Core/VectorBlock.h create mode 100644 doc/examples/class_FixedVectorBlock.cpp create mode 100644 doc/examples/class_VectorBlock.cpp diff --git a/Eigen/Core b/Eigen/Core index ace3a204e..0d3650c99 100644 --- a/Eigen/Core +++ b/Eigen/Core @@ -164,6 +164,7 @@ namespace Eigen { #include "src/Core/MapBase.h" #include "src/Core/Map.h" #include "src/Core/Block.h" +#include "src/Core/VectorBlock.h" #include "src/Core/Minor.h" #include "src/Core/Transpose.h" #include "src/Core/DiagonalMatrix.h" diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h index de4268344..d7af971f9 100644 --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -314,249 +314,6 @@ inline const typename BlockReturnType::Type MatrixBase return typename BlockReturnType::Type(derived(), startRow, startCol, blockRows, blockCols); } -/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this. - * - * \only_for_vectors - * - * \addexample SegmentIntInt \label How to reference a sub-vector (dynamic size) - * - * \param start the first coefficient in the segment - * \param size the number of coefficients in the segment - * - * Example: \include MatrixBase_segment_int_int.cpp - * Output: \verbinclude MatrixBase_segment_int_int.out - * - * \note Even though the returned expression has dynamic size, in the case - * when it is applied to a fixed-size vector, it inherits a fixed maximal size, - * which means that evaluating it does not cause a dynamic memory allocation. - * - * \sa class Block, segment(int) - */ -template -inline typename BlockReturnType::SubVectorType MatrixBase - ::segment(int start, int size) -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename BlockReturnType::SubVectorType(derived(), RowsAtCompileTime == 1 ? 0 : start, - ColsAtCompileTime == 1 ? 0 : start, - RowsAtCompileTime == 1 ? 1 : size, - ColsAtCompileTime == 1 ? 1 : size); -} - -/** This is the const version of segment(int,int).*/ -template -inline const typename BlockReturnType::SubVectorType -MatrixBase::segment(int start, int size) const -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return typename BlockReturnType::SubVectorType(derived(), RowsAtCompileTime == 1 ? 0 : start, - ColsAtCompileTime == 1 ? 0 : start, - RowsAtCompileTime == 1 ? 1 : size, - ColsAtCompileTime == 1 ? 1 : size); -} - -/** \returns a dynamic-size expression of the first coefficients of *this. - * - * \only_for_vectors - * - * \param size the number of coefficients in the block - * - * \addexample BlockInt \label How to reference a sub-vector (fixed-size) - * - * Example: \include MatrixBase_start_int.cpp - * Output: \verbinclude MatrixBase_start_int.out - * - * \note Even though the returned expression has dynamic size, in the case - * when it is applied to a fixed-size vector, it inherits a fixed maximal size, - * which means that evaluating it does not cause a dynamic memory allocation. - * - * \sa class Block, block(int,int) - */ -template -inline typename BlockReturnType::SubVectorType -MatrixBase::start(int size) -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), 0, 0, - RowsAtCompileTime == 1 ? 1 : size, - ColsAtCompileTime == 1 ? 1 : size); -} - -/** This is the const version of start(int).*/ -template -inline const typename BlockReturnType::SubVectorType -MatrixBase::start(int size) const -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), 0, 0, - RowsAtCompileTime == 1 ? 1 : size, - ColsAtCompileTime == 1 ? 1 : size); -} - -/** \returns a dynamic-size expression of the last coefficients of *this. - * - * \only_for_vectors - * - * \param size the number of coefficients in the block - * - * \addexample BlockEnd \label How to reference the end of a vector (fixed-size) - * - * Example: \include MatrixBase_end_int.cpp - * Output: \verbinclude MatrixBase_end_int.out - * - * \note Even though the returned expression has dynamic size, in the case - * when it is applied to a fixed-size vector, it inherits a fixed maximal size, - * which means that evaluating it does not cause a dynamic memory allocation. - * - * \sa class Block, block(int,int) - */ -template -inline typename BlockReturnType::SubVectorType -MatrixBase::end(int size) -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), - RowsAtCompileTime == 1 ? 0 : rows() - size, - ColsAtCompileTime == 1 ? 0 : cols() - size, - RowsAtCompileTime == 1 ? 1 : size, - ColsAtCompileTime == 1 ? 1 : size); -} - -/** This is the const version of end(int).*/ -template -inline const typename BlockReturnType::SubVectorType -MatrixBase::end(int size) const -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), - RowsAtCompileTime == 1 ? 0 : rows() - size, - ColsAtCompileTime == 1 ? 0 : cols() - size, - RowsAtCompileTime == 1 ? 1 : size, - ColsAtCompileTime == 1 ? 1 : size); -} - -/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this - * - * \only_for_vectors - * - * The template parameter \a Size is the number of coefficients in the block - * - * \param start the index of the first element of the sub-vector - * - * Example: \include MatrixBase_template_int_segment.cpp - * Output: \verbinclude MatrixBase_template_int_segment.out - * - * \sa class Block - */ -template -template -inline typename BlockReturnType::SubVectorType -MatrixBase::segment(int start) -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), RowsAtCompileTime == 1 ? 0 : start, - ColsAtCompileTime == 1 ? 0 : start); -} - -/** This is the const version of segment(int).*/ -template -template -inline const typename BlockReturnType::SubVectorType -MatrixBase::segment(int start) const -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), RowsAtCompileTime == 1 ? 0 : start, - ColsAtCompileTime == 1 ? 0 : start); -} - -/** \returns a fixed-size expression of the first coefficients of *this. - * - * \only_for_vectors - * - * The template parameter \a Size is the number of coefficients in the block - * - * \addexample BlockStart \label How to reference the start of a vector (fixed-size) - * - * Example: \include MatrixBase_template_int_start.cpp - * Output: \verbinclude MatrixBase_template_int_start.out - * - * \sa class Block - */ -template -template -inline typename BlockReturnType::SubVectorType -MatrixBase::start() -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block(derived(), 0, 0); -} - -/** This is the const version of start().*/ -template -template -inline const typename BlockReturnType::SubVectorType -MatrixBase::start() const -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block(derived(), 0, 0); -} - -/** \returns a fixed-size expression of the last coefficients of *this. - * - * \only_for_vectors - * - * The template parameter \a Size is the number of coefficients in the block - * - * Example: \include MatrixBase_template_int_end.cpp - * Output: \verbinclude MatrixBase_template_int_end.out - * - * \sa class Block - */ -template -template -inline typename BlockReturnType::SubVectorType -MatrixBase::end() -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), - RowsAtCompileTime == 1 ? 0 : rows() - Size, - ColsAtCompileTime == 1 ? 0 : cols() - Size); -} - -/** This is the const version of end.*/ -template -template -inline const typename BlockReturnType::SubVectorType -MatrixBase::end() const -{ - EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) - return Block - (derived(), - RowsAtCompileTime == 1 ? 0 : rows() - Size, - ColsAtCompileTime == 1 ? 0 : cols() - Size); -} - /** \returns a dynamic-size expression of a corner of *this. * * \param type the type of corner. Can be \a Eigen::TopLeft, \a Eigen::TopRight, diff --git a/Eigen/src/Core/MatrixBase.h b/Eigen/src/Core/MatrixBase.h index f925e0b0f..65ab02d62 100644 --- a/Eigen/src/Core/MatrixBase.h +++ b/Eigen/src/Core/MatrixBase.h @@ -401,14 +401,14 @@ template class MatrixBase const typename BlockReturnType::Type block(int startRow, int startCol, int blockRows, int blockCols) const; - typename BlockReturnType::SubVectorType segment(int start, int size); - const typename BlockReturnType::SubVectorType segment(int start, int size) const; + VectorBlock segment(int start, int size); + const VectorBlock segment(int start, int size) const; - typename BlockReturnType::SubVectorType start(int size); - const typename BlockReturnType::SubVectorType start(int size) const; + VectorBlock start(int size); + const VectorBlock start(int size) const; - typename BlockReturnType::SubVectorType end(int size); - const typename BlockReturnType::SubVectorType end(int size) const; + VectorBlock end(int size); + const VectorBlock end(int size) const; typename BlockReturnType::Type corner(CornerType type, int cRows, int cCols); const typename BlockReturnType::Type corner(CornerType type, int cRows, int cCols) const; @@ -423,14 +423,14 @@ template class MatrixBase template const typename BlockReturnType::Type corner(CornerType type) const; - template typename BlockReturnType::SubVectorType start(void); - template const typename BlockReturnType::SubVectorType start() const; + template VectorBlock start(void); + template const VectorBlock start() const; - template typename BlockReturnType::SubVectorType end(); - template const typename BlockReturnType::SubVectorType end() const; + template VectorBlock end(); + template const VectorBlock end() const; - template typename BlockReturnType::SubVectorType segment(int start); - template const typename BlockReturnType::SubVectorType segment(int start) const; + template VectorBlock segment(int start); + template const VectorBlock segment(int start) const; Diagonal diagonal(); const Diagonal diagonal() const; diff --git a/Eigen/src/Core/VectorBlock.h b/Eigen/src/Core/VectorBlock.h new file mode 100644 index 000000000..7ce5977f6 --- /dev/null +++ b/Eigen/src/Core/VectorBlock.h @@ -0,0 +1,311 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2009 Gael Guennebaud +// Copyright (C) 2006-2008 Benoit Jacob +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see . + +#ifndef EIGEN_VECTORBLOCK_H +#define EIGEN_VECTORBLOCK_H + +/** \class VectorBlock + * + * \brief Expression of a fixed-size or dynamic-size sub-vector + * + * \param VectorType the type of the object in which we are taking a sub-vector + * \param Size size of the sub-vector we are taking at compile time (optional) + * \param _PacketAccess allows to enforce aligned loads and stores if set to ForceAligned. + * The default is AsRequested. This parameter is internaly used by Eigen + * in expressions such as \code mat.segment() += other; \endcode and most of + * the time this is the only way it is used. + * + * This class represents an expression of either a fixed-size or dynamic-size sub-vector. + * It is the return type of MatrixBase::segment(int,int) and MatrixBase::segment(int) and + * most of the time this is the only way it is used. + * + * However, if you want to directly maniputate sub-vector expressions, + * for instance if you want to write a function returning such an expression, you + * will need to use this class. + * + * Here is an example illustrating the dynamic case: + * \include class_VectorBlock.cpp + * Output: \verbinclude class_VectorBlock.out + * + * \note Even though this expression has dynamic size, in the case where \a VectorType + * has fixed size, this expression inherits a fixed maximal size which means that evaluating + * it does not cause a dynamic memory allocation. + * + * Here is an example illustrating the fixed-size case: + * \include class_FixedVectorBlock.cpp + * Output: \verbinclude class_FixedVectorBlock.out + * + * \sa class Block, MatrixBase::segment(int,int,int,int), MatrixBase::segment(int,int) + */ +template +struct ei_traits > + : public ei_traits::RowsAtCompileTime==1 ? 1 : Size, + ei_traits::ColsAtCompileTime==1 ? 1 : Size, + _PacketAccess> > +{ +}; + +template class VectorBlock + : public Block::RowsAtCompileTime==1 ? 1 : Size, + ei_traits::ColsAtCompileTime==1 ? 1 : Size, + PacketAccess> +{ + typedef Block::RowsAtCompileTime==1 ? 1 : Size, + ei_traits::ColsAtCompileTime==1 ? 1 : Size, + PacketAccess> Base; + enum { + IsColVector = ei_traits::ColsAtCompileTime==1 + }; + public: + + using Base::operator=; + using Base::operator+=; + using Base::operator-=; + using Base::operator*=; + using Base::operator/=; + + /** Dynamic-size constructor + */ + inline VectorBlock(const VectorType& vector, int start, int size) + : Base(vector, + IsColVector ? start : 0, IsColVector ? 0 : start, + IsColVector ? size : 1, IsColVector ? 1 : size) + { + + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } + + /** Fixed-size constructor + */ + inline VectorBlock(const VectorType& vector, int start) + : Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } +}; + + +/** \returns a dynamic-size expression of a segment (i.e. a vector block) in *this. + * + * \only_for_vectors + * + * \addexample VectorBlockIntInt \label How to reference a sub-vector (dynamic size) + * + * \param start the first coefficient in the segment + * \param size the number of coefficients in the segment + * + * Example: \include MatrixBase_segment_int_int.cpp + * Output: \verbinclude MatrixBase_segment_int_int.out + * + * \note Even though the returned expression has dynamic size, in the case + * when it is applied to a fixed-size vector, it inherits a fixed maximal size, + * which means that evaluating it does not cause a dynamic memory allocation. + * + * \sa class Block, segment(int) + */ +template +inline VectorBlock MatrixBase + ::segment(int start, int size) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), start, size); +} + +/** This is the const version of segment(int,int).*/ +template +inline const VectorBlock +MatrixBase::segment(int start, int size) const +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), start, size); +} + +/** \returns a dynamic-size expression of the first coefficients of *this. + * + * \only_for_vectors + * + * \param size the number of coefficients in the block + * + * \addexample BlockInt \label How to reference a sub-vector (fixed-size) + * + * Example: \include MatrixBase_start_int.cpp + * Output: \verbinclude MatrixBase_start_int.out + * + * \note Even though the returned expression has dynamic size, in the case + * when it is applied to a fixed-size vector, it inherits a fixed maximal size, + * which means that evaluating it does not cause a dynamic memory allocation. + * + * \sa class Block, block(int,int) + */ +template +inline VectorBlock +MatrixBase::start(int size) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), 0, size); +} + +/** This is the const version of start(int).*/ +template +inline const VectorBlock +MatrixBase::start(int size) const +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), 0, size); +} + +/** \returns a dynamic-size expression of the last coefficients of *this. + * + * \only_for_vectors + * + * \param size the number of coefficients in the block + * + * \addexample BlockEnd \label How to reference the end of a vector (fixed-size) + * + * Example: \include MatrixBase_end_int.cpp + * Output: \verbinclude MatrixBase_end_int.out + * + * \note Even though the returned expression has dynamic size, in the case + * when it is applied to a fixed-size vector, it inherits a fixed maximal size, + * which means that evaluating it does not cause a dynamic memory allocation. + * + * \sa class Block, block(int,int) + */ +template +inline VectorBlock +MatrixBase::end(int size) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), this->size() - size, size); +} + +/** This is the const version of end(int).*/ +template +inline const VectorBlock +MatrixBase::end(int size) const +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), this->size() - size, size); +} + +/** \returns a fixed-size expression of a segment (i.e. a vector block) in \c *this + * + * \only_for_vectors + * + * The template parameter \a Size is the number of coefficients in the block + * + * \param start the index of the first element of the sub-vector + * + * Example: \include MatrixBase_template_int_segment.cpp + * Output: \verbinclude MatrixBase_template_int_segment.out + * + * \sa class Block + */ +template +template +inline VectorBlock +MatrixBase::segment(int start) +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), start); +} + +/** This is the const version of segment(int).*/ +template +template +inline const VectorBlock +MatrixBase::segment(int start) const +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), start); +} + +/** \returns a fixed-size expression of the first coefficients of *this. + * + * \only_for_vectors + * + * The template parameter \a Size is the number of coefficients in the block + * + * \addexample BlockStart \label How to reference the start of a vector (fixed-size) + * + * Example: \include MatrixBase_template_int_start.cpp + * Output: \verbinclude MatrixBase_template_int_start.out + * + * \sa class Block + */ +template +template +inline VectorBlock +MatrixBase::start() +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), 0); +} + +/** This is the const version of start().*/ +template +template +inline const VectorBlock +MatrixBase::start() const +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), 0); +} + +/** \returns a fixed-size expression of the last coefficients of *this. + * + * \only_for_vectors + * + * The template parameter \a Size is the number of coefficients in the block + * + * Example: \include MatrixBase_template_int_end.cpp + * Output: \verbinclude MatrixBase_template_int_end.out + * + * \sa class Block + */ +template +template +inline VectorBlock +MatrixBase::end() +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), size() - Size); +} + +/** This is the const version of end.*/ +template +template +inline const VectorBlock +MatrixBase::end() const +{ + EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived) + return VectorBlock(derived(), size() - Size); +} + + +#endif // EIGEN_VECTORBLOCK_H diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h index 9606771a1..b457268af 100644 --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -39,6 +39,7 @@ template class Minor; template::Flags&DirectAccessBit ? DirectAccessBit : ei_traits::Flags&SparseBit> class Block; +template class VectorBlock; template class Transpose; template class Conjugate; template class CwiseNullaryOp; diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h index 7b139b0c1..b8d6aeb35 100644 --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -237,8 +237,6 @@ struct ei_special_scalar_op_base * TODO: could be a good idea to define a big ReturnType struct ?? */ template struct BlockReturnType { - typedef Block::RowsAtCompileTime == 1 ? 1 : RowsOrSize), - (ei_traits::ColsAtCompileTime == 1 ? 1 : RowsOrSize)> SubVectorType; typedef Block Type; }; diff --git a/doc/examples/class_FixedVectorBlock.cpp b/doc/examples/class_FixedVectorBlock.cpp new file mode 100644 index 000000000..c176be495 --- /dev/null +++ b/doc/examples/class_FixedVectorBlock.cpp @@ -0,0 +1,26 @@ +#include +USING_PART_OF_NAMESPACE_EIGEN +using namespace std; + +template +Eigen::VectorBlock +firstTwo(MatrixBase& v) +{ + return Eigen::VectorBlock(v.derived(), 0); +} + +template +const Eigen::VectorBlock +firstTwo(const MatrixBase& v) +{ + return Eigen::VectorBlock(v.derived(), 0); +} + +int main(int, char**) +{ + Matrix v; v << 1,2,3,4,5,6; + cout << firstTwo(4*v) << endl; // calls the const version + firstTwo(v) *= 2; // calls the non-const version + cout << "Now the vector v is:" << endl << v << endl; + return 0; +} diff --git a/doc/examples/class_VectorBlock.cpp b/doc/examples/class_VectorBlock.cpp new file mode 100644 index 000000000..d979f973a --- /dev/null +++ b/doc/examples/class_VectorBlock.cpp @@ -0,0 +1,26 @@ +#include +USING_PART_OF_NAMESPACE_EIGEN +using namespace std; + +template +Eigen::VectorBlock +segmentFromRange(MatrixBase& v, int start, int end) +{ + return Eigen::VectorBlock(v.derived(), start, end-start); +} + +template +const Eigen::VectorBlock +segmentFromRange(const MatrixBase& v, int start, int end) +{ + return Eigen::VectorBlock(v.derived(), start, end-start); +} + +int main(int, char**) +{ + Matrix v; v << 1,2,3,4,5,6; + cout << segmentFromRange(2*v, 2, 4) << endl; // calls the const version + segmentFromRange(v, 1, 3) *= 5; // calls the non-const version + cout << "Now the vector v is:" << endl << v << endl; + return 0; +}