diff --git a/Eigen/src/Core/Block.h b/Eigen/src/Core/Block.h --- a/Eigen/src/Core/Block.h +++ b/Eigen/src/Core/Block.h @@ -1,12 +1,12 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008 Gael Guennebaud +// Copyright (C) 2008-2016 Gael Guennebaud // Copyright (C) 2006-2010 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_BLOCK_H #define EIGEN_BLOCK_H @@ -49,17 +49,17 @@ struct traits::value ? LvalueBit : 0, FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, Flags = (traits::Flags & (DirectAccessBit | (InnerPanel?CompressedAccessBit:0))) | FlagsLvalueBit | FlagsRowMajorBit, // FIXME DirectAccessBit should not be handled by expressions // // Alignment is needed by MapBase's assertions - // We can sefely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the respective evaluator + // We can safely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the respective evaluator Alignment = 0 }; }; template::ret> class BlockImpl_dense; } // end namespace internal @@ -141,19 +141,172 @@ template= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows && startCol >= 0 && blockCols >= 0 && startCol <= xpr.cols() - blockCols); } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef Block::RowsAtCompileTime, 1, InnerPanel && (!Base::IsRowMajor)> ColXpr; + typedef const Block::RowsAtCompileTime, 1, InnerPanel && (!Base::IsRowMajor)> ConstColXpr; + typedef Block::ColsAtCompileTime, InnerPanel && Base::IsRowMajor> RowXpr; + typedef const Block::ColsAtCompileTime, InnerPanel && Base::IsRowMajor> ConstRowXpr; + typedef Block::RowsAtCompileTime, Dynamic, InnerPanel && (!Base::IsRowMajor)> ColsBlockXpr; + typedef const Block::RowsAtCompileTime, Dynamic, InnerPanel && (!Base::IsRowMajor)> ConstColsBlockXpr; + typedef Block::ColsAtCompileTime, InnerPanel && Base::IsRowMajor> RowsBlockXpr; + typedef const Block::ColsAtCompileTime, InnerPanel && Base::IsRowMajor> ConstRowsBlockXpr; + template struct NColsBlockXpr { typedef Block::RowsAtCompileTime, N, InnerPanel && (!Base::IsRowMajor)> Type; }; + template struct ConstNColsBlockXpr { typedef const Block::RowsAtCompileTime, N, InnerPanel && (!Base::IsRowMajor)> Type; }; + template struct NRowsBlockXpr { typedef Block::ColsAtCompileTime, InnerPanel && Base::IsRowMajor> Type; }; + template struct ConstNRowsBlockXpr { typedef const Block::ColsAtCompileTime, InnerPanel && Base::IsRowMajor> Type; }; + typedef Block BlockXpr; + typedef const Block ConstBlockXpr; + template struct FixedBlockXpr { typedef Block Type; }; + template struct ConstFixedBlockXpr { typedef Block Type; }; + + enum { + IsColVector = internal::is_column_vector_at_compile_time::value + }; + + typedef VectorBlock SegmentReturnType; + typedef const VectorBlock ConstSegmentReturnType; + template struct FixedSegmentReturnType { typedef VectorBlock Type; }; + template struct ConstFixedSegmentReturnType { typedef const VectorBlock Type; }; + + using Base::rows; + using Base::cols; + using Base::size; + #define EIGEN_BLOCK_METHODS_SKIP_TYPEDEFS + typedef Block Derived; + #include "../plugins/BlockMethods.h" + #undef EIGEN_BLOCK_METHODS_SKIP_TYPEDEFS + + typedef typename internal::remove_const::type XprTypeNonConst; + + template + EIGEN_DEVICE_FUNC + inline Block( Block &blk, Index i) + : Impl(blk.nestedExpression(), + blk.startRow() + ((BlockRows==1) && (BlockCols==Block::ColsAtCompileTime) ? i : 0), + blk.startCol() + ((BlockRows==Block::RowsAtCompileTime) && (BlockCols==1) ? i : 0), + BlockRows==1 ? 1 : blk.rows(), + BlockCols==1 ? 1 : blk.cols() + ) + { + eigen_assert( (i>=0) && ( + ((BlockRows==1) && (BlockCols==Block::ColsAtCompileTime) && i::RowsAtCompileTime) && (BlockCols==1) && i + EIGEN_DEVICE_FUNC + inline Block(Block &blk, Index startRow, Index startCol) + : Impl(blk.nestedExpression(), + blk.startRow() + startRow, + blk.startCol() + startCol) + { + EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) + eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= blk.rows() + && startCol >= 0 && BlockCols >= 0 && startCol + BlockCols <= blk.cols()); + } + + template + EIGEN_DEVICE_FUNC + inline Block(Block &blk, Index startRow, Index startCol, Index blockRows, Index blockCols) + : Impl(blk.nestedExpression(), blk.startRow() + startRow, blk.startCol() + startCol, blockRows, blockCols) + { + eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) + && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); + eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= blk.rows() - blockRows + && startCol >= 0 && blockCols >= 0 && startCol <= blk.cols() - blockCols); + } + + template + EIGEN_DEVICE_FUNC + inline Block( const Block &blk, Index i) + : Impl(blk.nestedExpression(), + blk.startRow() + ((BlockRows==1) && (BlockCols==Block::ColsAtCompileTime) ? i : 0), + blk.startCol() + ((BlockRows==Block::RowsAtCompileTime) && (BlockCols==1) ? i : 0), + BlockRows==1 ? 1 : blk.rows(), + BlockCols==1 ? 1 : blk.cols() + ) + { + eigen_assert( (i>=0) && ( + ((BlockRows==1) && (BlockCols==Block::ColsAtCompileTime) && i::RowsAtCompileTime) && (BlockCols==1) && i + EIGEN_DEVICE_FUNC + inline Block(const Block &blk, Index startRow, Index startCol) + : Impl(blk.nestedExpression(), + blk.startRow() + startRow, + blk.startCol() + startCol) + { + EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) + eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= blk.rows() + && startCol >= 0 && BlockCols >= 0 && startCol + BlockCols <= blk.cols()); + } + + template + EIGEN_DEVICE_FUNC + inline Block(const Block &blk, Index startRow, Index startCol, Index blockRows, Index blockCols) + : Impl(blk.nestedExpression(), blk.startRow() + startRow, blk.startCol() + startCol, blockRows, blockCols) + { + eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) + && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); + eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= blk.rows() - blockRows + && startCol >= 0 && blockCols >= 0 && startCol <= blk.cols() - blockCols); + } + + template + EIGEN_DEVICE_FUNC + inline Block( const Block &blk, Index i) + : Impl(blk.nestedExpression(), + blk.startRow() + ((BlockRows==1) && (BlockCols==Block::ColsAtCompileTime) ? i : 0), + blk.startCol() + ((BlockRows==Block::RowsAtCompileTime) && (BlockCols==1) ? i : 0), + BlockRows==1 ? 1 : blk.rows(), + BlockCols==1 ? 1 : blk.cols() + ) + { + eigen_assert( (i>=0) && ( + ((BlockRows==1) && (BlockCols==Block::ColsAtCompileTime) && i::RowsAtCompileTime) && (BlockCols==1) && i + EIGEN_DEVICE_FUNC + inline Block(const Block &blk, Index startRow, Index startCol) + : Impl(blk.nestedExpression(), + blk.startRow() + startRow, + blk.startCol() + startCol) + { + EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) + eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= blk.rows() + && startCol >= 0 && BlockCols >= 0 && startCol + BlockCols <= blk.cols()); + } + + template + EIGEN_DEVICE_FUNC + inline Block(const Block &blk, Index startRow, Index startCol, Index blockRows, Index blockCols) + : Impl(blk.nestedExpression(), blk.startRow() + startRow, blk.startCol() + startCol, blockRows, blockCols) + { + eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) + && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); + eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= blk.rows() - blockRows + && startCol >= 0 && blockCols >= 0 && startCol <= blk.cols() - blockCols); + } +#endif + }; - -// The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense + +// The generic default implementation for dense block simply forward to the internal::BlockImpl_dense // that must be specialized for direct and non-direct access... template class BlockImpl : public internal::BlockImpl_dense { typedef internal::BlockImpl_dense Impl; typedef typename XprType::StorageIndex StorageIndex; public: diff --git a/Eigen/src/Core/VectorBlock.h b/Eigen/src/Core/VectorBlock.h --- a/Eigen/src/Core/VectorBlock.h +++ b/Eigen/src/Core/VectorBlock.h @@ -9,23 +9,20 @@ // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_VECTORBLOCK_H #define EIGEN_VECTORBLOCK_H namespace Eigen { namespace internal { -template -struct traits > - : public traits::Flags & RowMajorBit ? 1 : Size, - traits::Flags & RowMajorBit ? Size : 1> > -{ -}; +template +struct traits > + : public traits > +{}; } /** \class VectorBlock * \ingroup Core_Module * * \brief Expression of a fixed-size or dynamic-size sub-vector * * \tparam VectorType the type of the object in which we are taking a sub-vector @@ -48,27 +45,21 @@ struct traits class VectorBlock - : public Block::Flags & RowMajorBit ? 1 : Size, - internal::traits::Flags & RowMajorBit ? Size : 1> +template class VectorBlock + : public Block { - typedef Block::Flags & RowMajorBit ? 1 : Size, - internal::traits::Flags & RowMajorBit ? Size : 1> Base; - enum { - IsColVector = !(internal::traits::Flags & RowMajorBit) - }; + typedef Block Base; + public: EIGEN_DENSE_PUBLIC_INTERFACE(VectorBlock) using Base::operator=; /** Dynamic-size constructor */ EIGEN_DEVICE_FUNC @@ -83,14 +74,76 @@ template /** Fixed-size constructor */ EIGEN_DEVICE_FUNC inline VectorBlock(VectorType& vector, Index start) : Base(vector, IsColVector ? start : 0, IsColVector ? 0 : start) { EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); } + +#ifndef EIGEN_PARSED_BY_DOXYGEN + typedef typename Base::XprTypeNonConst XprTypeNonConst; + template + EIGEN_DEVICE_FUNC + inline VectorBlock(Block &blk, Index start, Index size) + : Base(blk.nestedExpression(), + blk.startRow() + (IsColVector ? start : 0), + blk.startCol() + (IsColVector ? 0 : start), + IsColVector ? size : 1, IsColVector ? 1 : size) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } + + template + EIGEN_DEVICE_FUNC + inline VectorBlock(Block &blk, Index start) + : Base(blk.nestedExpression(), blk.startRow() + (IsColVector ? start : 0), blk.startCol() + (IsColVector ? 0 : start)) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } + + + template + EIGEN_DEVICE_FUNC + inline VectorBlock(const Block &blk, Index start, Index size) + : Base(blk.nestedExpression(), + blk.startRow() + (IsColVector ? start : 0), + blk.startCol() + (IsColVector ? 0 : start), + IsColVector ? size : 1, IsColVector ? 1 : size) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } + + template + EIGEN_DEVICE_FUNC + inline VectorBlock(const Block &blk, Index start) + : Base(blk.nestedExpression(), blk.startRow() + (IsColVector ? start : 0), blk.startCol() + (IsColVector ? 0 : start)) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } + + + template + EIGEN_DEVICE_FUNC + inline VectorBlock(const Block &blk, Index start, Index size) + : Base(blk.nestedExpression(), + blk.startRow() + (IsColVector ? start : 0), + blk.startCol() + (IsColVector ? 0 : start), + IsColVector ? size : 1, IsColVector ? 1 : size) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } + + template + EIGEN_DEVICE_FUNC + inline VectorBlock(const Block &blk, Index start) + : Base(blk.nestedExpression(), blk.startRow() + (IsColVector ? start : 0), blk.startCol() + (IsColVector ? 0 : start)) + { + EIGEN_STATIC_ASSERT_VECTOR_ONLY(VectorBlock); + } +#endif }; } // end namespace Eigen #endif // EIGEN_VECTORBLOCK_H diff --git a/Eigen/src/Core/util/ForwardDeclarations.h b/Eigen/src/Core/util/ForwardDeclarations.h --- a/Eigen/src/Core/util/ForwardDeclarations.h +++ b/Eigen/src/Core/util/ForwardDeclarations.h @@ -35,16 +35,18 @@ template struct access : (has_write_access ? WriteAccessors : ReadOnlyAccessors) }; }; template struct evaluator_traits; template< typename T> struct evaluator; +template struct is_column_vector_at_compile_time; + } // end namespace internal template struct NumTraits; template struct EigenBase; template class DenseBase; template class PlainObjectBase; @@ -79,17 +81,17 @@ template class ArrayBa template class Flagged; template class StorageBase > class NoAlias; template class NestByValue; template class ForceAlignedAccess; template class SwapWrapper; template class Block; -template class VectorBlock; +template::value> class VectorBlock; template class Transpose; template class Conjugate; template class CwiseNullaryOp; template class CwiseUnaryOp; template class CwiseUnaryView; template class CwiseBinaryOp; template class Solve; template class Inverse; diff --git a/Eigen/src/Core/util/XprHelper.h b/Eigen/src/Core/util/XprHelper.h --- a/Eigen/src/Core/util/XprHelper.h +++ b/Eigen/src/Core/util/XprHelper.h @@ -223,16 +223,25 @@ template struct si enum { ret = (_Rows==Dynamic || _Cols==Dynamic) ? Dynamic : _Rows * _Cols }; }; template struct size_of_xpr_at_compile_time { enum { ret = size_at_compile_time::RowsAtCompileTime,traits::ColsAtCompileTime>::ret }; }; +template struct is_column_vector_at_compile_time +{ + enum { + value = (internal::traits::ColsAtCompileTime==1 && internal::traits::RowsAtCompileTime==1) + ? (!(internal::traits::Flags & RowMajorBit)) + : (internal::traits::ColsAtCompileTime==1) + }; +}; + /* plain_matrix_type : the difference from eval is that plain_matrix_type is always a plain matrix type, * whereas eval is a const reference in the case of a matrix */ template::StorageKind> struct plain_matrix_type; template struct plain_matrix_type_dense; template struct plain_matrix_type { @@ -656,17 +665,17 @@ bool is_same_dense(const T1 &, const T2 return false; } template struct is_same_or_void { enum { value = is_same::value }; }; template struct is_same_or_void { enum { value = 1 }; }; template struct is_same_or_void { enum { value = 1 }; }; template<> struct is_same_or_void { enum { value = 1 }; }; -#ifdef EIGEN_DEBUG_ASSIGN +#if defined EIGEN_DEBUG_ASSIGN || defined EIGEN_DEBUG_DEMANGLING std::string demangle_traversal(int t) { if(t==DefaultTraversal) return "DefaultTraversal"; if(t==LinearTraversal) return "LinearTraversal"; if(t==InnerVectorizedTraversal) return "InnerVectorizedTraversal"; if(t==LinearVectorizedTraversal) return "LinearVectorizedTraversal"; if(t==SliceVectorizedTraversal) return "SliceVectorizedTraversal"; return "?"; diff --git a/Eigen/src/plugins/BlockMethods.h b/Eigen/src/plugins/BlockMethods.h --- a/Eigen/src/plugins/BlockMethods.h +++ b/Eigen/src/plugins/BlockMethods.h @@ -5,16 +5,17 @@ // Copyright (C) 2006-2010 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_PARSED_BY_DOXYGEN +#ifndef EIGEN_BLOCK_METHODS_SKIP_TYPEDEFS /** \internal expression type of a column */ typedef Block::RowsAtCompileTime, 1, !IsRowMajor> ColXpr; typedef const Block::RowsAtCompileTime, 1, !IsRowMajor> ConstColXpr; /** \internal expression type of a row */ typedef Block::ColsAtCompileTime, IsRowMajor> RowXpr; typedef const Block::ColsAtCompileTime, IsRowMajor> ConstRowXpr; /** \internal expression type of a block of whole columns */ typedef Block::RowsAtCompileTime, Dynamic, !IsRowMajor> ColsBlockXpr; @@ -34,16 +35,17 @@ typedef const Block Const /** \internal expression of a block of fixed sizes */ template struct FixedBlockXpr { typedef Block Type; }; template struct ConstFixedBlockXpr { typedef Block Type; }; typedef VectorBlock SegmentReturnType; typedef const VectorBlock ConstSegmentReturnType; template struct FixedSegmentReturnType { typedef VectorBlock Type; }; template struct ConstFixedSegmentReturnType { typedef const VectorBlock Type; }; +#endif #endif // not EIGEN_PARSED_BY_DOXYGEN /** \returns a dynamic-size expression of a block in *this. * * \param startRow the first row in the block * \param startCol the first column in the block * \param blockRows the number of rows in the block diff --git a/test/block.cpp b/test/block.cpp --- a/test/block.cpp +++ b/test/block.cpp @@ -3,16 +3,17 @@ // // Copyright (C) 2006-2010 Benoit Jacob // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #define EIGEN_NO_STATIC_ASSERT // otherwise we fail at compile time on unused paths +#define EIGEN_DEBUG_DEMANGLING #include "main.h" template typename Eigen::internal::enable_if::IsComplex,typename MatrixType::Scalar>::type block_real_only(const MatrixType &m1, Index r1, Index r2, Index c1, Index c2, const Scalar& s1) { // check cwise-Functions: VERIFY_IS_APPROX(m1.row(r1).cwiseMax(s1), m1.cwiseMax(s1).row(r1)); VERIFY_IS_APPROX(m1.col(c1).cwiseMin(s1), m1.cwiseMin(s1).col(c1)); @@ -183,16 +184,168 @@ template void block VERIFY_IS_EQUAL(dv, dm); VERIFY_IS_EQUAL( (m1.template block(1,0,0,1)), m1.block(1,0,0,1)); VERIFY_IS_EQUAL( (m1.template block<1,Dynamic>(0,1,1,0)), m1.block(0,1,1,0)); VERIFY_IS_EQUAL( ((m1*1).template block(1,0,0,1)), m1.block(1,0,0,1)); VERIFY_IS_EQUAL( ((m1*1).template block<1,Dynamic>(0,1,1,0)), m1.block(0,1,1,0)); } +template +bool same_type(const T&, const T&) { return true; } + +template +void checkbb(const DenseBase &a_xpr, const DenseBase &a_ref, const DenseBase &a_xprfused) +{ + const Expr& xpr(a_xpr.derived());TRACK; + const Ref& ref(a_ref.derived());TRACK; + const ExprFused& xprfused(a_xprfused.derived());TRACK; + + VERIFY_IS_APPROX(xprfused, ref);TRACK; + + VERIFY(same_type(xpr, xprfused));TRACK; + + if(ExprFused::Flags!=Expr::Flags) + std::cerr << "Expected: " << internal::demangle_flags(ExprFused::Flags) << std::endl + << "Got: " << internal::demangle_flags(Expr::Flags) << std::endl; + + VERIFY_IS_EQUAL(ExprFused::Flags, Expr::Flags);TRACK; + VERIFY_IS_EQUAL(ExprFused::RowsAtCompileTime, Expr::RowsAtCompileTime);TRACK; + VERIFY_IS_EQUAL(ExprFused::ColsAtCompileTime, Expr::ColsAtCompileTime);TRACK; + + typedef internal::evaluator EvalFused;TRACK; + typedef internal::evaluator EvalExpr;TRACK; + VERIFY_IS_EQUAL(EvalFused::Flags, EvalExpr::Flags);TRACK; + VERIFY_IS_EQUAL(EvalFused::Alignment, EvalExpr::Alignment);TRACK; + + VERIFY_IS_APPROX(xpr.derived(), ref);TRACK; + VERIFY_IS_APPROX(xpr, ref);TRACK; +} + +template +void block_rec(const MatrixType& a) +{ + if(a.cols()>1) + { + block_rec(a.leftCols(a.cols()/2)); + block_rec(a.rightCols(a.cols()/2)); + } +} + +template const T& make_const(const T& x) { return x; } + +template +void check_block_block_fusion(const MatrixType &m) +{ + Index rows = m.rows(); + Index cols = m.cols(); + + MatrixType m1 = MatrixType::Random(rows, cols), + m2 = MatrixType::Random(rows, cols); + + Index r1 = internal::random(0,rows-1); + Index c1 = internal::random(0,cols-1); + Index nr1 = internal::random(1,rows-r1); + Index nc1 = internal::random(1,cols-c1); + + Index r2 = internal::random(0,nr1-1); + Index c2 = internal::random(0,nc1-1); + Index nr2 = internal::random(1,nr1-r2); + Index nc2 = internal::random(1,nc1-c2); + + CALL_SUBTEST( checkbb(m1.block(r1,c1, nr1,nc1).block(r2,c2,nr2,nc2), + m1.block(r1,c1, nr1,nc1).eval().block(r2,c2,nr2,nc2).eval(), + m1.block(r1+r2, c1+c2, nr2, nc2)) ); + CALL_SUBTEST( checkbb(make_const(m1.block(r1,c1, nr1,nc1)).block(r2,c2,nr2,nc2), + m1.block(r1,c1, nr1,nc1).eval().block(r2,c2,nr2,nc2).eval(), + make_const(m1).block(r1+r2, c1+c2, nr2, nc2)) ); + CALL_SUBTEST( checkbb((m1+m2).block(r1,c1, nr1,nc1).block(r2,c2,nr2,nc2), + (m1+m2).block(r1,c1, nr1,nc1).eval().block(r2,c2,nr2,nc2).eval(), + (m1+m2).block(r1+r2, c1+c2, nr2, nc2)) ); + + CALL_SUBTEST( checkbb(m1.block(r1,c1, nr1,nc1).row(r2), + m1.block(r1,c1, nr1,nc1).eval().row(r2).eval(), + m1.template block<1,Dynamic>(r1+r2, c1, 1, nc1)) ); + CALL_SUBTEST( checkbb(make_const(m1.block(r1,c1, nr1,nc1)).row(r2), + m1.block(r1,c1, nr1,nc1).eval().row(r2).eval(), + make_const(m1).template block<1,Dynamic>(r1+r2, c1, 1, nc1)) ); + CALL_SUBTEST( checkbb((m1+m2).block(r1,c1, nr1,nc1).row(r2), + (m1+m2).block(r1,c1, nr1,nc1).eval().row(r2).eval(), + (m1+m2).template block<1,Dynamic>(r1+r2, c1, 1, nc1)) ); + + CALL_SUBTEST( checkbb(m1.block(r1,c1, nr1,nc1).col(c2), + m1.block(r1,c1, nr1,nc1).eval().col(c2).eval(), + m1.template block(r1, c1+c2, nr1, 1)) ); + CALL_SUBTEST( checkbb(make_const(m1.block(r1,c1, nr1,nc1)).col(c2), + m1.block(r1,c1, nr1,nc1).eval().col(c2).eval(), + make_const(m1).template block(r1, c1+c2, nr1, 1)) ); + CALL_SUBTEST( checkbb((m1+m2).block(r1,c1, nr1,nc1).col(c2), + (m1+m2).block(r1,c1, nr1,nc1).eval().col(c2).eval(), + (m1+m2).template block(r1, c1+c2, nr1, 1)) ); + + CALL_SUBTEST( checkbb(m1.row(r1).segment(c1,nc1), + m1.row(r1).eval().segment(c1,nc1).eval(), + m1.template block<1,Dynamic>(r1, c1, 1, nc1)) ); + CALL_SUBTEST( checkbb(make_const(m1.row(r1)).segment(c1,nc1), + m1.row(r1).eval().segment(c1,nc1).eval(), + make_const(m1).template block<1,Dynamic>(r1, c1, 1, nc1)) ); + CALL_SUBTEST( checkbb((m1+m2).row(r1).segment(c1,nc1), + (m1+m2).row(r1).eval().segment(c1,nc1).eval(), + (m1+m2).template block<1,Dynamic>(r1, c1, 1, nc1)) ); + + CALL_SUBTEST( checkbb(m1.col(c1).segment(r1,nr1), + m1.col(c1).eval().segment(r1,nr1).eval(), + m1.template block(r1, c1, nr1, 1)) ); + CALL_SUBTEST( checkbb(make_const(m1.col(c1)).segment(r1,nr1), + m1.col(c1).eval().segment(r1,nr1).eval(), + make_const(m1).template block(r1, c1, nr1, 1)) ); + CALL_SUBTEST( checkbb((m1+m2).col(c1).segment(r1,nr1), + (m1+m2).col(c1).eval().segment(r1,nr1).eval(), + (m1+m2).template block(r1, c1, nr1, 1)) ); + + CALL_SUBTEST( checkbb(m1.middleCols(c1,nc1).col(c2).segment(r1,nr1), + m1.middleCols(c1,nc1).eval().col(c2).eval().segment(r1,nr1).eval(), + m1.template block(r1, c1+c2, nr1, 1)) ); + CALL_SUBTEST( checkbb(make_const(m1.middleCols(c1,nc1)).col(c2).segment(r1,nr1), + m1.middleCols(c1,nc1).eval().col(c2).eval().segment(r1,nr1).eval(), + make_const(m1).template block(r1, c1+c2, nr1, 1)) ); + CALL_SUBTEST( checkbb(make_const(m1.middleCols(c1,nc1).col(c2)).segment(r1,nr1), + m1.middleCols(c1,nc1).eval().col(c2).eval().segment(r1,nr1).eval(), + make_const(m1).template block(r1, c1+c2, nr1, 1)) ); + CALL_SUBTEST( checkbb((m1+m2).middleCols(c1,nc1).col(c2).segment(r1,nr1), + (m1+m2).middleCols(c1,nc1).eval().col(c2).eval().segment(r1,nr1).eval(), + (m1+m2).template block(r1, c1+c2, nr1, 1)) ); + + CALL_SUBTEST( checkbb(m1.row(r1).col(c1), + m1.row(r1).eval().col(c1).eval(), + m1.template block<1,1>(r1, c1)) ); + CALL_SUBTEST( checkbb(make_const(m1.row(r1)).col(c1), + m1.row(r1).eval().col(c1).eval(), + make_const(m1).template block<1,1>(r1, c1)) ); + CALL_SUBTEST( checkbb((m1+m2).row(r1).col(c1), + (m1+m2).row(r1).eval().col(c1).eval(), + (m1+m2).template block<1,1>(r1, c1)) ); + + CALL_SUBTEST( checkbb(m1.row(r1).col(c1).segment(0,1), + m1.row(r1).eval().col(c1).eval().segment(0,1).eval(), + m1.template block(r1, c1, 1,1)) ); + CALL_SUBTEST( checkbb(make_const(m1.row(r1)).col(c1).segment(0,1), + m1.row(r1).eval().col(c1).eval().segment(0,1).eval(), + make_const(m1).template block(r1, c1, 1,1)) ); + CALL_SUBTEST( checkbb(make_const(m1.row(r1).col(c1)).segment(0,1), + m1.row(r1).eval().col(c1).eval().segment(0,1).eval(), + make_const(m1).template block(r1, c1, 1,1)) ); + CALL_SUBTEST( checkbb((m1+m2).row(r1).col(c1).segment(0,1), + (m1+m2).row(r1).eval().col(c1).eval().segment(0,1).eval(), + (m1+m2).template block(r1, c1, 1,1)) ); + + block_rec(m1); + block_rec(m1+m2); + block_rec(m1.transpose()); +} template void compare_using_data_and_stride(const MatrixType& m) { typedef typename MatrixType::Index Index; Index rows = m.rows(); Index cols = m.cols(); Index size = m.size(); @@ -251,14 +404,23 @@ void test_block() CALL_SUBTEST_2( block(Matrix4d()) ); CALL_SUBTEST_3( block(MatrixXcf(3, 3)) ); CALL_SUBTEST_4( block(MatrixXi(8, 12)) ); CALL_SUBTEST_5( block(MatrixXcd(20, 20)) ); CALL_SUBTEST_6( block(MatrixXf(20, 20)) ); CALL_SUBTEST_8( block(Matrix(3, 4)) ); + CALL_SUBTEST_9( check_block_block_fusion(MatrixXi(internal::random(1,50), internal::random(1,50))) ); + CALL_SUBTEST_9( check_block_block_fusion(Matrix4i()) ); + CALL_SUBTEST_9( check_block_block_fusion(Matrix3i()) ); + + CALL_SUBTEST_9( check_block_block_fusion(MatrixXd(internal::random(1,50), internal::random(1,50))) ); + CALL_SUBTEST_9( check_block_block_fusion(Matrix4d()) ); + CALL_SUBTEST_9( check_block_block_fusion(Matrix3d()) ); + CALL_SUBTEST_9( check_block_block_fusion(Matrix2d()) ); + #ifndef EIGEN_DEFAULT_TO_ROW_MAJOR CALL_SUBTEST_6( data_and_stride(MatrixXf(internal::random(5,50), internal::random(5,50))) ); CALL_SUBTEST_7( data_and_stride(Matrix(internal::random(5,50), internal::random(5,50))) ); #endif } }