| 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 | |
| 14 | namespace Eigen { |
| 15 | |
| 16 | namespace internal { |
| 17 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> |
| 18 | struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprType> |
| 19 | { |
| 20 | typedef typename traits<XprType>::Scalar Scalar; |
| 21 | typedef typename traits<XprType>::StorageKind StorageKind; |
| 22 | typedef typename traits<XprType>::XprKind XprKind; |
| 23 | typedef typename ref_selector<XprType>::type XprTypeNested; |
| 24 | typedef typename remove_reference<XprTypeNested>::type _XprTypeNested; |
| 25 | enum{ |
| 26 | MatrixRows = traits<XprType>::RowsAtCompileTime, |
| 27 | MatrixCols = traits<XprType>::ColsAtCompileTime, |
| 28 | RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows, |
| 29 | ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols, |
| 30 | MaxRowsAtCompileTime = BlockRows==0 ? 0 |
| 31 | : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime) |
| 32 | : int(traits<XprType>::MaxRowsAtCompileTime), |
| 33 | MaxColsAtCompileTime = BlockCols==0 ? 0 |
| 34 | : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime) |
| 35 | : int(traits<XprType>::MaxColsAtCompileTime), |
| 36 | |
| 37 | XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0, |
| 38 | IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1 |
| 39 | : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0 |
| 40 | : XprTypeIsRowMajor, |
| 41 | HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor), |
| 42 | InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime), |
| 43 | InnerStrideAtCompileTime = HasSameStorageOrderAsXprType |
| 44 | ? int(inner_stride_at_compile_time<XprType>::ret) |
| 45 | : int(outer_stride_at_compile_time<XprType>::ret), |
| 46 | OuterStrideAtCompileTime = HasSameStorageOrderAsXprType |
| 47 | ? int(outer_stride_at_compile_time<XprType>::ret) |
| 48 | : int(inner_stride_at_compile_time<XprType>::ret), |
| 49 | |
| 50 | // FIXME, this traits is rather specialized for dense object and it needs to be cleaned further |
| 51 | FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0, |
| 52 | FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0, |
| 53 | Flags = (traits<XprType>::Flags & (DirectAccessBit | (InnerPanel?CompressedAccessBit:0))) | FlagsLvalueBit | FlagsRowMajorBit, |
| 54 | // FIXME DirectAccessBit should not be handled by expressions |
| 55 | // |
| 56 | // Alignment is needed by MapBase's assertions |
| 57 | // We can sefely set it to false here. Internal alignment errors will be detected by an eigen_internal_assert in the respective evaluator |
| 58 | Alignment = 0 |
| 59 | }; |
| 60 | }; |
| 61 | |
| 62 | template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false, |
| 63 | bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class BlockImpl_dense; |
| 64 | |
| 65 | } // end namespace internal |
| 66 | |
| 67 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind> class BlockImpl; |
| 68 | |
| 69 | /** \class Block |
| 70 | * \ingroup Core_Module |
| 71 | * |
| 72 | * \brief Expression of a fixed-size or dynamic-size block |
| 73 | * |
| 74 | * \tparam XprType the type of the expression in which we are taking a block |
| 75 | * \tparam BlockRows the number of rows of the block we are taking at compile time (optional) |
| 76 | * \tparam BlockCols the number of columns of the block we are taking at compile time (optional) |
| 77 | * \tparam InnerPanel is true, if the block maps to a set of rows of a row major matrix or |
| 78 | * to set of columns of a column major matrix (optional). The parameter allows to determine |
| 79 | * at compile time whether aligned access is possible on the block expression. |
| 80 | * |
| 81 | * This class represents an expression of either a fixed-size or dynamic-size block. It is the return |
| 82 | * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and |
| 83 | * most of the time this is the only way it is used. |
| 84 | * |
| 85 | * However, if you want to directly maniputate block expressions, |
| 86 | * for instance if you want to write a function returning such an expression, you |
| 87 | * will need to use this class. |
| 88 | * |
| 89 | * Here is an example illustrating the dynamic case: |
| 90 | * \include class_Block.cpp |
| 91 | * Output: \verbinclude class_Block.out |
| 92 | * |
| 93 | * \note Even though this expression has dynamic size, in the case where \a XprType |
| 94 | * has fixed size, this expression inherits a fixed maximal size which means that evaluating |
| 95 | * it does not cause a dynamic memory allocation. |
| 96 | * |
| 97 | * Here is an example illustrating the fixed-size case: |
| 98 | * \include class_FixedBlock.cpp |
| 99 | * Output: \verbinclude class_FixedBlock.out |
| 100 | * |
| 101 | * \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock |
| 102 | */ |
| 103 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class Block |
| 104 | : public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> |
| 105 | { |
| 106 | typedef BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> Impl; |
| 107 | public: |
| 108 | //typedef typename Impl::Base Base; |
| 109 | typedef Impl Base; |
| 110 | EIGEN_GENERIC_PUBLIC_INTERFACE(Block) |
| 111 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block) |
| 112 | |
| 113 | typedef typename internal::remove_all<XprType>::type NestedExpression; |
| 114 | |
| 115 | /** Column or Row constructor |
| 116 | */ |
| 117 | EIGEN_DEVICE_FUNC |
| 118 | inline Block(XprType& xpr, Index i) : Impl(xpr,i) |
| 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 | EIGEN_DEVICE_FUNC |
| 128 | inline Block(XprType& xpr, Index startRow, Index startCol) |
| 129 | : Impl(xpr, startRow, startCol) |
| 130 | { |
| 131 | EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE) |
| 132 | eigen_assert(startRow >= 0 && BlockRows >= 0 && startRow + BlockRows <= xpr.rows() |
| 133 | && startCol >= 0 && BlockCols >= 0 && startCol + BlockCols <= xpr.cols()); |
| 134 | } |
| 135 | |
| 136 | /** Dynamic-size constructor |
| 137 | */ |
| 138 | EIGEN_DEVICE_FUNC |
| 139 | inline Block(XprType& xpr, |
| 140 | Index startRow, Index startCol, |
| 141 | Index blockRows, Index blockCols) |
| 142 | : Impl(xpr, startRow, startCol, blockRows, blockCols) |
| 143 | { |
| 144 | eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows) |
| 145 | && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols)); |
| 146 | eigen_assert(startRow >= 0 && blockRows >= 0 && startRow <= xpr.rows() - blockRows |
| 147 | && startCol >= 0 && blockCols >= 0 && startCol <= xpr.cols() - blockCols); |
| 148 | } |
| 149 | }; |
| 150 | |
| 151 | // The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense |
| 152 | // that must be specialized for direct and non-direct access... |
| 153 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> |
| 154 | class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense> |
| 155 | : public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> |
| 156 | { |
| 157 | typedef internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> Impl; |
| 158 | typedef typename XprType::StorageIndex StorageIndex; |
| 159 | public: |
| 160 | typedef Impl Base; |
| 161 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl) |
| 162 | EIGEN_DEVICE_FUNC inline BlockImpl(XprType& xpr, Index i) : Impl(xpr,i) {} |
| 163 | EIGEN_DEVICE_FUNC inline BlockImpl(XprType& xpr, Index startRow, Index startCol) : Impl(xpr, startRow, startCol) {} |
| 164 | EIGEN_DEVICE_FUNC |
| 165 | inline BlockImpl(XprType& xpr, Index startRow, Index startCol, Index blockRows, Index blockCols) |
| 166 | : Impl(xpr, startRow, startCol, blockRows, blockCols) {} |
| 167 | }; |
| 168 | |
| 169 | namespace internal { |
| 170 | |
| 171 | /** \internal Internal implementation of dense Blocks in the general case. */ |
| 172 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class BlockImpl_dense |
| 173 | : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel> >::type |
| 174 | { |
| 175 | typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType; |
| 176 | typedef typename internal::ref_selector<XprType>::non_const_type XprTypeNested; |
| 177 | public: |
| 178 | |
| 179 | typedef typename internal::dense_xpr_base<BlockType>::type Base; |
| 180 | EIGEN_DENSE_PUBLIC_INTERFACE(BlockType) |
| 181 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense) |
| 182 | |
| 183 | // class InnerIterator; // FIXME apparently never used |
| 184 | |
| 185 | /** Column or Row constructor |
| 186 | */ |
| 187 | EIGEN_DEVICE_FUNC |
| 188 | inline BlockImpl_dense(XprType& xpr, Index i) |
| 189 | : m_xpr(xpr), |
| 190 | // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime, |
| 191 | // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1, |
| 192 | // all other cases are invalid. |
| 193 | // The case a 1x1 matrix seems ambiguous, but the result is the same anyway. |
| 194 | m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0), |
| 195 | m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0), |
| 196 | m_blockRows(BlockRows==1 ? 1 : xpr.rows()), |
| 197 | m_blockCols(BlockCols==1 ? 1 : xpr.cols()) |
| 198 | {} |
| 199 | |
| 200 | /** Fixed-size constructor |
| 201 | */ |
| 202 | EIGEN_DEVICE_FUNC |
| 203 | inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol) |
| 204 | : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), |
| 205 | m_blockRows(BlockRows), m_blockCols(BlockCols) |
| 206 | {} |
| 207 | |
| 208 | /** Dynamic-size constructor |
| 209 | */ |
| 210 | EIGEN_DEVICE_FUNC |
| 211 | inline BlockImpl_dense(XprType& xpr, |
| 212 | Index startRow, Index startCol, |
| 213 | Index blockRows, Index blockCols) |
| 214 | : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol), |
| 215 | m_blockRows(blockRows), m_blockCols(blockCols) |
| 216 | {} |
| 217 | |
| 218 | EIGEN_DEVICE_FUNC inline Index rows() const { return m_blockRows.value(); } |
| 219 | EIGEN_DEVICE_FUNC inline Index cols() const { return m_blockCols.value(); } |
| 220 | |
| 221 | EIGEN_DEVICE_FUNC |
| 222 | inline Scalar& coeffRef(Index rowId, Index colId) |
| 223 | { |
| 224 | EIGEN_STATIC_ASSERT_LVALUE(XprType) |
| 225 | return m_xpr.coeffRef(rowId + m_startRow.value(), colId + m_startCol.value()); |
| 226 | } |
| 227 | |
| 228 | EIGEN_DEVICE_FUNC |
| 229 | inline const Scalar& coeffRef(Index rowId, Index colId) const |
| 230 | { |
| 231 | return m_xpr.derived().coeffRef(rowId + m_startRow.value(), colId + m_startCol.value()); |
| 232 | } |
| 233 | |
| 234 | EIGEN_DEVICE_FUNC |
| 235 | EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const |
| 236 | { |
| 237 | return m_xpr.coeff(rowId + m_startRow.value(), colId + m_startCol.value()); |
| 238 | } |
| 239 | |
| 240 | EIGEN_DEVICE_FUNC |
| 241 | inline Scalar& coeffRef(Index index) |
| 242 | { |
| 243 | EIGEN_STATIC_ASSERT_LVALUE(XprType) |
| 244 | return m_xpr.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
| 245 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
| 246 | } |
| 247 | |
| 248 | EIGEN_DEVICE_FUNC |
| 249 | inline const Scalar& coeffRef(Index index) const |
| 250 | { |
| 251 | return m_xpr.coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
| 252 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
| 253 | } |
| 254 | |
| 255 | EIGEN_DEVICE_FUNC |
| 256 | inline const CoeffReturnType coeff(Index index) const |
| 257 | { |
| 258 | return m_xpr.coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
| 259 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
| 260 | } |
| 261 | |
| 262 | template<int LoadMode> |
| 263 | inline PacketScalar packet(Index rowId, Index colId) const |
| 264 | { |
| 265 | return m_xpr.template packet<Unaligned>(rowId + m_startRow.value(), colId + m_startCol.value()); |
| 266 | } |
| 267 | |
| 268 | template<int LoadMode> |
| 269 | inline void writePacket(Index rowId, Index colId, const PacketScalar& val) |
| 270 | { |
| 271 | m_xpr.template writePacket<Unaligned>(rowId + m_startRow.value(), colId + m_startCol.value(), val); |
| 272 | } |
| 273 | |
| 274 | template<int LoadMode> |
| 275 | inline PacketScalar packet(Index index) const |
| 276 | { |
| 277 | return m_xpr.template packet<Unaligned> |
| 278 | (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
| 279 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0)); |
| 280 | } |
| 281 | |
| 282 | template<int LoadMode> |
| 283 | inline void writePacket(Index index, const PacketScalar& val) |
| 284 | { |
| 285 | m_xpr.template writePacket<Unaligned> |
| 286 | (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index), |
| 287 | m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), val); |
| 288 | } |
| 289 | |
| 290 | #ifdef EIGEN_PARSED_BY_DOXYGEN |
| 291 | /** \sa MapBase::data() */ |
| 292 | EIGEN_DEVICE_FUNC inline const Scalar* data() const; |
| 293 | EIGEN_DEVICE_FUNC inline Index innerStride() const; |
| 294 | EIGEN_DEVICE_FUNC inline Index outerStride() const; |
| 295 | #endif |
| 296 | |
| 297 | EIGEN_DEVICE_FUNC |
| 298 | const typename internal::remove_all<XprTypeNested>::type& nestedExpression() const |
| 299 | { |
| 300 | return m_xpr; |
| 301 | } |
| 302 | |
| 303 | EIGEN_DEVICE_FUNC |
| 304 | XprType& nestedExpression() { return m_xpr; } |
| 305 | |
| 306 | EIGEN_DEVICE_FUNC |
| 307 | StorageIndex startRow() const |
| 308 | { |
| 309 | return m_startRow.value(); |
| 310 | } |
| 311 | |
| 312 | EIGEN_DEVICE_FUNC |
| 313 | StorageIndex startCol() const |
| 314 | { |
| 315 | return m_startCol.value(); |
| 316 | } |
| 317 | |
| 318 | protected: |
| 319 | |
| 320 | XprTypeNested m_xpr; |
| 321 | const internal::variable_if_dynamic<StorageIndex, (XprType::RowsAtCompileTime == 1 && BlockRows==1) ? 0 : Dynamic> m_startRow; |
| 322 | const internal::variable_if_dynamic<StorageIndex, (XprType::ColsAtCompileTime == 1 && BlockCols==1) ? 0 : Dynamic> m_startCol; |
| 323 | const internal::variable_if_dynamic<StorageIndex, RowsAtCompileTime> m_blockRows; |
| 324 | const internal::variable_if_dynamic<StorageIndex, ColsAtCompileTime> m_blockCols; |
| 325 | }; |
| 326 | |
| 327 | /** \internal Internal implementation of dense Blocks in the direct access case.*/ |
| 328 | template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> |
| 329 | class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true> |
| 330 | : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> > |
| 331 | { |
| 332 | typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType; |
| 333 | typedef typename internal::ref_selector<XprType>::non_const_type XprTypeNested; |
| 334 | enum { |
| 335 | XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0 |
| 336 | }; |
| 337 | public: |
| 338 | |
| 339 | typedef MapBase<BlockType> Base; |
| 340 | EIGEN_DENSE_PUBLIC_INTERFACE(BlockType) |
| 341 | EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense) |
| 342 | |
| 343 | /** Column or Row constructor |
| 344 | */ |
| 345 | EIGEN_DEVICE_FUNC |
| 346 | inline BlockImpl_dense(XprType& xpr, Index i) |
| 347 | : Base(xpr.data() + i * ( ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && (!XprTypeIsRowMajor)) |
| 348 | || ((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && ( XprTypeIsRowMajor)) ? xpr.innerStride() : xpr.outerStride()), |
| 349 | BlockRows==1 ? 1 : xpr.rows(), |
| 350 | BlockCols==1 ? 1 : xpr.cols()), |
| 351 | m_xpr(xpr), |
| 352 | m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0), |
| 353 | m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0) |
| 354 | { |
| 355 | init(); |
| 356 | } |
| 357 | |
| 358 | /** Fixed-size constructor |
| 359 | */ |
| 360 | EIGEN_DEVICE_FUNC |
| 361 | inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol) |
| 362 | : Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol)), |
| 363 | m_xpr(xpr), m_startRow(startRow), m_startCol(startCol) |
| 364 | { |
| 365 | init(); |
| 366 | } |
| 367 | |
| 368 | /** Dynamic-size constructor |
| 369 | */ |
| 370 | EIGEN_DEVICE_FUNC |
| 371 | inline BlockImpl_dense(XprType& xpr, |
| 372 | Index startRow, Index startCol, |
| 373 | Index blockRows, Index blockCols) |
| 374 | : Base(xpr.data()+xpr.innerStride()*(XprTypeIsRowMajor?startCol:startRow) + xpr.outerStride()*(XprTypeIsRowMajor?startRow:startCol), blockRows, blockCols), |
| 375 | m_xpr(xpr), m_startRow(startRow), m_startCol(startCol) |
| 376 | { |
| 377 | init(); |
| 378 | } |
| 379 | |
| 380 | EIGEN_DEVICE_FUNC |
| 381 | const typename internal::remove_all<XprTypeNested>::type& nestedExpression() const |
| 382 | { |
| 383 | return m_xpr; |
| 384 | } |
| 385 | |
| 386 | EIGEN_DEVICE_FUNC |
| 387 | XprType& nestedExpression() { return m_xpr; } |
| 388 | |
| 389 | /** \sa MapBase::innerStride() */ |
| 390 | EIGEN_DEVICE_FUNC |
| 391 | inline Index innerStride() const |
| 392 | { |
| 393 | return internal::traits<BlockType>::HasSameStorageOrderAsXprType |
| 394 | ? m_xpr.innerStride() |
| 395 | : m_xpr.outerStride(); |
| 396 | } |
| 397 | |
| 398 | /** \sa MapBase::outerStride() */ |
| 399 | EIGEN_DEVICE_FUNC |
| 400 | inline Index outerStride() const |
| 401 | { |
| 402 | return m_outerStride; |
| 403 | } |
| 404 | |
| 405 | EIGEN_DEVICE_FUNC |
| 406 | StorageIndex startRow() const |
| 407 | { |
| 408 | return m_startRow.value(); |
| 409 | } |
| 410 | |
| 411 | EIGEN_DEVICE_FUNC |
| 412 | StorageIndex startCol() const |
| 413 | { |
| 414 | return m_startCol.value(); |
| 415 | } |
| 416 | |
| 417 | #ifndef __SUNPRO_CC |
| 418 | // FIXME sunstudio is not friendly with the above friend... |
| 419 | // META-FIXME there is no 'friend' keyword around here. Is this obsolete? |
| 420 | protected: |
| 421 | #endif |
| 422 | |
| 423 | #ifndef EIGEN_PARSED_BY_DOXYGEN |
| 424 | /** \internal used by allowAligned() */ |
| 425 | EIGEN_DEVICE_FUNC |
| 426 | inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols) |
| 427 | : Base(data, blockRows, blockCols), m_xpr(xpr) |
| 428 | { |
| 429 | init(); |
| 430 | } |
| 431 | #endif |
| 432 | |
| 433 | protected: |
| 434 | EIGEN_DEVICE_FUNC |
| 435 | void init() |
| 436 | { |
| 437 | m_outerStride = internal::traits<BlockType>::HasSameStorageOrderAsXprType |
| 438 | ? m_xpr.outerStride() |
| 439 | : m_xpr.innerStride(); |
| 440 | } |
| 441 | |
| 442 | XprTypeNested m_xpr; |
| 443 | const internal::variable_if_dynamic<StorageIndex, (XprType::RowsAtCompileTime == 1 && BlockRows==1) ? 0 : Dynamic> m_startRow; |
| 444 | const internal::variable_if_dynamic<StorageIndex, (XprType::ColsAtCompileTime == 1 && BlockCols==1) ? 0 : Dynamic> m_startCol; |
| 445 | Index m_outerStride; |
| 446 | }; |
| 447 | |
| 448 | } // end namespace internal |
| 449 | |
| 450 | } // end namespace Eigen |
| 451 | |
| 452 | #endif // EIGEN_BLOCK_H |
| 453 | |