1// This file is part of Eigen, a lightweight C++ template library 2// for linear algebra. 3// 4// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 5// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com> 6// 7// This Source Code Form is subject to the terms of the Mozilla 8// Public License v. 2.0. If a copy of the MPL was not distributed 9// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 10 11#ifndef EIGEN_BLOCK_H 12#define EIGEN_BLOCK_H 13 14namespace Eigen { 15 16/** \class Block 17 * \ingroup Core_Module 18 * 19 * \brief Expression of a fixed-size or dynamic-size block 20 * 21 * \param XprType the type of the expression in which we are taking a block 22 * \param BlockRows the number of rows of the block we are taking at compile time (optional) 23 * \param BlockCols the number of columns of the block we are taking at compile time (optional) 24 * \param _DirectAccessStatus \internal used for partial specialization 25 * 26 * This class represents an expression of either a fixed-size or dynamic-size block. It is the return 27 * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and 28 * most of the time this is the only way it is used. 29 * 30 * However, if you want to directly maniputate block expressions, 31 * for instance if you want to write a function returning such an expression, you 32 * will need to use this class. 33 * 34 * Here is an example illustrating the dynamic case: 35 * \include class_Block.cpp 36 * Output: \verbinclude class_Block.out 37 * 38 * \note Even though this expression has dynamic size, in the case where \a XprType 39 * has fixed size, this expression inherits a fixed maximal size which means that evaluating 40 * it does not cause a dynamic memory allocation. 41 * 42 * Here is an example illustrating the fixed-size case: 43 * \include class_FixedBlock.cpp 44 * Output: \verbinclude class_FixedBlock.out 45 * 46 * \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock 47 */ 48 49namespace internal { 50template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> 51struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType> 52{ 53 typedef typename traits<XprType>::Scalar Scalar; 54 typedef typename traits<XprType>::StorageKind StorageKind; 55 typedef typename traits<XprType>::XprKind XprKind; 56 typedef typename nested<XprType>::type XprTypeNested; 57 typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; 58 enum{ 59 MatrixRows = traits<XprType>::RowsAtCompileTime, 60 MatrixCols = traits<XprType>::ColsAtCompileTime, 61 RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows, 62 ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols, 63 MaxRowsAtCompileTime = BlockRows==0 ? 0 64 : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) 65 : int(traits<XprType>::MaxRowsAtCompileTime), 66 MaxColsAtCompileTime = BlockCols==0 ? 0 67 : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) 68 : int(traits<XprType>::MaxColsAtCompileTime), 69 XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0, 70 IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1 71 : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0 72 : XprTypeIsRowMajor, 73 HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), 74 InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime), 75 InnerStrideAtCompileTime = HasSameStorageOrderAsXprType 76 ? int(inner_stride_at_compile_time<XprType>::ret) 77 : int(outer_stride_at_compile_time<XprType>::ret), 78 OuterStrideAtCompileTime = HasSameStorageOrderAsXprType 79 ? int(outer_stride_at_compile_time<XprType>::ret) 80 : int(inner_stride_at_compile_time<XprType>::ret), 81 MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0) 82 && (InnerStrideAtCompileTime == 1) 83 ? PacketAccessBit : 0, 84 MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0, 85 FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0, 86 FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0, 87 FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, 88 Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) | 89 DirectAccessBit | 90 MaskPacketAccessBit | 91 MaskAlignedBit), 92 Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit 93 }; 94}; 95} 96 97template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block 98 : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type 99{ 100 public: 101 102 typedef typename internal::dense_xpr_base<Block>::type Base; 103 EIGEN_DENSE_PUBLIC_INTERFACE(Block) 104 105 class InnerIterator; 106 107 /** Column or Row constructor 108 */ 109 inline Block(XprType& xpr, Index i) 110 : m_xpr(xpr), 111 // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime, 112 // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1, 113 // all other cases are invalid. 114 // The case a 1x1 matrix seems ambiguous, but the result is the same anyway. 115 m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0), 116 m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0), 117 m_blockRows(BlockRows==1 ? 1 : xpr.rows()), 118 m_blockCols(BlockCols==1 ? 1 : xpr.cols()) 119 { 120 eigen_assert( (i>=0) && ( 121 ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) 122 ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols()))); 123 } 124 125 /** Fixed-size constructor 126 */ 127 inline Block(XprType& xpr, Index startRow, Index startCol) 128 : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), 129 m_blockRows(BlockRows), m_blockCols(BlockCols) 130 { 131 EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) 132 eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows() 133 && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols()); 134 } 135 136 /** Dynamic-size constructor 137 */ 138 inline Block(XprType& xpr, 139 Index startRow, Index startCol, 140 Index blockRows, Index blockCols) 141 : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), 142 m_blockRows(blockRows), m_blockCols(blockCols) 143 { 144 eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) 145 && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); 146 eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows() 147 && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols()); 148 } 149 150 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) 151 152 inline Index rows() const { return m_blockRows.value(); } 153 inline Index cols() const { return m_blockCols.value(); } 154 155 inline Scalar& coeffRef(Index row, Index col) 156 { 157 EIGEN_STATIC_ASSERT_LVALUE(XprType) 158 return m_xpr.const_cast_derived() 159 .coeffRef(row + m_startRow.value(), col + m_startCol.value()); 160 } 161 162 inline const Scalar& coeffRef(Index row, Index col) const 163 { 164 return m_xpr.derived() 165 .coeffRef(row + m_startRow.value(), col + m_startCol.value()); 166 } 167 168 EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const 169 { 170 return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value()); 171 } 172 173 inline Scalar& coeffRef(Index index) 174 { 175 EIGEN_STATIC_ASSERT_LVALUE(XprType) 176 return m_xpr.const_cast_derived() 177 .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 178 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); 179 } 180 181 inline const Scalar& coeffRef(Index index) const 182 { 183 return m_xpr.const_cast_derived() 184 .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 185 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); 186 } 187 188 inline const CoeffReturnType coeff(Index index) const 189 { 190 return m_xpr 191 .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 192 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); 193 } 194 195 template<int LoadMode> 196 inline PacketScalar packet(Index row, Index col) const 197 { 198 return m_xpr.template packet<Unaligned> 199 (row + m_startRow.value(), col + m_startCol.value()); 200 } 201 202 template<int LoadMode> 203 inline void writePacket(Index row, Index col, const PacketScalar& x) 204 { 205 m_xpr.const_cast_derived().template writePacket<Unaligned> 206 (row + m_startRow.value(), col + m_startCol.value(), x); 207 } 208 209 template<int LoadMode> 210 inline PacketScalar packet(Index index) const 211 { 212 return m_xpr.template packet<Unaligned> 213 (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 214 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); 215 } 216 217 template<int LoadMode> 218 inline void writePacket(Index index, const PacketScalar& x) 219 { 220 m_xpr.const_cast_derived().template writePacket<Unaligned> 221 (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), 222 m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x); 223 } 224 225 #ifdef EIGEN_PARSED_BY_DOXYGEN 226 /** \sa MapBase::data() */ 227 inline const Scalar* data() const; 228 inline Index innerStride() const; 229 inline Index outerStride() const; 230 #endif 231 232 const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 233 { 234 return m_xpr; 235 } 236 237 Index startRow() const 238 { 239 return m_startRow.value(); 240 } 241 242 Index startCol() const 243 { 244 return m_startCol.value(); 245 } 246 247 protected: 248 249 const typename XprType::Nested m_xpr; 250 const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow; 251 const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol; 252 const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows; 253 const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols; 254}; 255 256/** \internal */ 257template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> 258class Block<XprType,BlockRows,BlockCols, InnerPanel,true> 259 : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> > 260{ 261 public: 262 263 typedef MapBase<Block> Base; 264 EIGEN_DENSE_PUBLIC_INTERFACE(Block) 265 266 EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) 267 268 /** Column or Row constructor 269 */ 270 inline Block(XprType& xpr, Index i) 271 : Base(internal::const_cast_ptr(&xpr.coeffRef( 272 (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0, 273 (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)), 274 BlockRows==1 ? 1 : xpr.rows(), 275 BlockCols==1 ? 1 : xpr.cols()), 276 m_xpr(xpr) 277 { 278 eigen_assert( (i>=0) && ( 279 ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows()) 280 ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols()))); 281 init(); 282 } 283 284 /** Fixed-size constructor 285 */ 286 inline Block(XprType& xpr, Index startRow, Index startCol) 287 : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr) 288 { 289 eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows() 290 && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols()); 291 init(); 292 } 293 294 /** Dynamic-size constructor 295 */ 296 inline Block(XprType& xpr, 297 Index startRow, Index startCol, 298 Index blockRows, Index blockCols) 299 : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols), 300 m_xpr(xpr) 301 { 302 eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) 303 && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); 304 eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows() 305 && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols()); 306 init(); 307 } 308 309 const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 310 { 311 return m_xpr; 312 } 313 314 /** \sa MapBase::innerStride() */ 315 inline Index innerStride() const 316 { 317 return internal::traits<Block>::HasSameStorageOrderAsXprType 318 ? m_xpr.innerStride() 319 : m_xpr.outerStride(); 320 } 321 322 /** \sa MapBase::outerStride() */ 323 inline Index outerStride() const 324 { 325 return m_outerStride; 326 } 327 328 #ifndef __SUNPRO_CC 329 // FIXME sunstudio is not friendly with the above friend... 330 // META-FIXME there is no 'friend' keyword around here. Is this obsolete? 331 protected: 332 #endif 333 334 #ifndef EIGEN_PARSED_BY_DOXYGEN 335 /** \internal used by allowAligned() */ 336 inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols) 337 : Base(data, blockRows, blockCols), m_xpr(xpr) 338 { 339 init(); 340 } 341 #endif 342 343 protected: 344 void init() 345 { 346 m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType 347 ? m_xpr.outerStride() 348 : m_xpr.innerStride(); 349 } 350 351 typename XprType::Nested m_xpr; 352 Index m_outerStride; 353}; 354 355} // end namespace Eigen 356 357#endif // EIGEN_BLOCK_H 358