Block.h 15.8 KB
Newer Older
LM's avatar
LM committed
1 2 3 4 5 6
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
// Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
//
Don Gagne's avatar
Don Gagne committed
7 8 9
// 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/.
LM's avatar
LM committed
10 11 12 13

#ifndef EIGEN_BLOCK_H
#define EIGEN_BLOCK_H

Don Gagne's avatar
Don Gagne committed
14 15
namespace Eigen { 

LM's avatar
LM committed
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/** \class Block
  * \ingroup Core_Module
  *
  * \brief Expression of a fixed-size or dynamic-size block
  *
  * \param XprType the type of the expression in which we are taking a block
  * \param BlockRows the number of rows of the block we are taking at compile time (optional)
  * \param BlockCols the number of columns of the block we are taking at compile time (optional)
  *
  * This class represents an expression of either a fixed-size or dynamic-size block. It is the return
  * type of DenseBase::block(Index,Index,Index,Index) and DenseBase::block<int,int>(Index,Index) and
  * most of the time this is the only way it is used.
  *
  * However, if you want to directly maniputate block 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_Block.cpp
  * Output: \verbinclude class_Block.out
  *
  * \note Even though this expression has dynamic size, in the case where \a XprType
  * 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_FixedBlock.cpp
  * Output: \verbinclude class_FixedBlock.out
  *
  * \sa DenseBase::block(Index,Index,Index,Index), DenseBase::block(Index,Index), class VectorBlock
  */

namespace internal {
Don Gagne's avatar
Don Gagne committed
49 50
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel> > : traits<XprType>
LM's avatar
LM committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
{
  typedef typename traits<XprType>::Scalar Scalar;
  typedef typename traits<XprType>::StorageKind StorageKind;
  typedef typename traits<XprType>::XprKind XprKind;
  typedef typename nested<XprType>::type XprTypeNested;
  typedef typename remove_reference<XprTypeNested>::type _XprTypeNested;
  enum{
    MatrixRows = traits<XprType>::RowsAtCompileTime,
    MatrixCols = traits<XprType>::ColsAtCompileTime,
    RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows,
    ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols,
    MaxRowsAtCompileTime = BlockRows==0 ? 0
                         : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime)
                         : int(traits<XprType>::MaxRowsAtCompileTime),
    MaxColsAtCompileTime = BlockCols==0 ? 0
                         : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
                         : int(traits<XprType>::MaxColsAtCompileTime),
    XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
    IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
               : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
               : XprTypeIsRowMajor,
    HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
    InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
    InnerStrideAtCompileTime = HasSameStorageOrderAsXprType
                             ? int(inner_stride_at_compile_time<XprType>::ret)
                             : int(outer_stride_at_compile_time<XprType>::ret),
    OuterStrideAtCompileTime = HasSameStorageOrderAsXprType
                             ? int(outer_stride_at_compile_time<XprType>::ret)
                             : int(inner_stride_at_compile_time<XprType>::ret),
    MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
                       && (InnerStrideAtCompileTime == 1)
                        ? PacketAccessBit : 0,
Don Gagne's avatar
Don Gagne committed
83
    MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
LM's avatar
LM committed
84 85 86 87 88 89 90 91 92 93 94
    FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
    FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
    FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
    Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
                                        DirectAccessBit |
                                        MaskPacketAccessBit |
                                        MaskAlignedBit),
    Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
  };
};

Don Gagne's avatar
Don Gagne committed
95 96 97 98
template<typename XprType, int BlockRows=Dynamic, int BlockCols=Dynamic, bool InnerPanel = false,
         bool HasDirectAccess = internal::has_direct_access<XprType>::ret> class BlockImpl_dense;
         
} // end namespace internal
LM's avatar
LM committed
99

Don Gagne's avatar
Don Gagne committed
100
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, typename StorageKind> class BlockImpl;
LM's avatar
LM committed
101

Don Gagne's avatar
Don Gagne committed
102 103 104 105 106 107 108 109 110 111
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel> class Block
  : public BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind>
{
    typedef BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, typename internal::traits<XprType>::StorageKind> Impl;
  public:
    //typedef typename Impl::Base Base;
    typedef Impl Base;
    EIGEN_GENERIC_PUBLIC_INTERFACE(Block)
    EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
  
LM's avatar
LM committed
112 113
    /** Column or Row constructor
      */
Don Gagne's avatar
Don Gagne committed
114
    inline Block(XprType& xpr, Index i) : Impl(xpr,i)
LM's avatar
LM committed
115 116 117 118 119 120 121 122
    {
      eigen_assert( (i>=0) && (
          ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
        ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
    }

    /** Fixed-size constructor
      */
Don Gagne's avatar
Don Gagne committed
123 124
    inline Block(XprType& xpr, Index a_startRow, Index a_startCol)
      : Impl(xpr, a_startRow, a_startCol)
LM's avatar
LM committed
125 126
    {
      EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
Don Gagne's avatar
Don Gagne committed
127 128
      eigen_assert(a_startRow >= 0 && BlockRows >= 1 && a_startRow + BlockRows <= xpr.rows()
             && a_startCol >= 0 && BlockCols >= 1 && a_startCol + BlockCols <= xpr.cols());
LM's avatar
LM committed
129 130 131 132 133
    }

    /** Dynamic-size constructor
      */
    inline Block(XprType& xpr,
Don Gagne's avatar
Don Gagne committed
134
          Index a_startRow, Index a_startCol,
LM's avatar
LM committed
135
          Index blockRows, Index blockCols)
Don Gagne's avatar
Don Gagne committed
136
      : Impl(xpr, a_startRow, a_startCol, blockRows, blockCols)
LM's avatar
LM committed
137 138 139
    {
      eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
          && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
Don Gagne's avatar
Don Gagne committed
140 141
      eigen_assert(a_startRow >= 0 && blockRows >= 0 && a_startRow  <= xpr.rows() - blockRows
          && a_startCol >= 0 && blockCols >= 0 && a_startCol <= xpr.cols() - blockCols);
LM's avatar
LM committed
142
    }
Don Gagne's avatar
Don Gagne committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
};
         
// The generic default implementation for dense block simplu forward to the internal::BlockImpl_dense
// that must be specialized for direct and non-direct access...
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
class BlockImpl<XprType, BlockRows, BlockCols, InnerPanel, Dense>
  : public internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel>
{
    typedef internal::BlockImpl_dense<XprType, BlockRows, BlockCols, InnerPanel> Impl;
    typedef typename XprType::Index Index;
  public:
    typedef Impl Base;
    EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl)
    inline BlockImpl(XprType& xpr, Index i) : Impl(xpr,i) {}
    inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol) : Impl(xpr, a_startRow, a_startCol) {}
    inline BlockImpl(XprType& xpr, Index a_startRow, Index a_startCol, Index blockRows, Index blockCols)
      : Impl(xpr, a_startRow, a_startCol, blockRows, blockCols) {}
};
LM's avatar
LM committed
161

Don Gagne's avatar
Don Gagne committed
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
namespace internal {

/** \internal Internal implementation of dense Blocks in the general case. */
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class BlockImpl_dense
  : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel> >::type
{
    typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
  public:

    typedef typename internal::dense_xpr_base<BlockType>::type Base;
    EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
    EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)

    class InnerIterator;

    /** Column or Row constructor
      */
    inline BlockImpl_dense(XprType& xpr, Index i)
      : m_xpr(xpr),
        // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
        // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
        // all other cases are invalid.
        // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
        m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
        m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
        m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
        m_blockCols(BlockCols==1 ? 1 : xpr.cols())
    {}

    /** Fixed-size constructor
      */
    inline BlockImpl_dense(XprType& xpr, Index a_startRow, Index a_startCol)
      : m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol),
                    m_blockRows(BlockRows), m_blockCols(BlockCols)
    {}

    /** Dynamic-size constructor
      */
    inline BlockImpl_dense(XprType& xpr,
          Index a_startRow, Index a_startCol,
          Index blockRows, Index blockCols)
      : m_xpr(xpr), m_startRow(a_startRow), m_startCol(a_startCol),
                    m_blockRows(blockRows), m_blockCols(blockCols)
    {}
LM's avatar
LM committed
206 207 208 209

    inline Index rows() const { return m_blockRows.value(); }
    inline Index cols() const { return m_blockCols.value(); }

Don Gagne's avatar
Don Gagne committed
210
    inline Scalar& coeffRef(Index rowId, Index colId)
LM's avatar
LM committed
211 212 213
    {
      EIGEN_STATIC_ASSERT_LVALUE(XprType)
      return m_xpr.const_cast_derived()
Don Gagne's avatar
Don Gagne committed
214
               .coeffRef(rowId + m_startRow.value(), colId + m_startCol.value());
LM's avatar
LM committed
215 216
    }

Don Gagne's avatar
Don Gagne committed
217
    inline const Scalar& coeffRef(Index rowId, Index colId) const
LM's avatar
LM committed
218 219
    {
      return m_xpr.derived()
Don Gagne's avatar
Don Gagne committed
220
               .coeffRef(rowId + m_startRow.value(), colId + m_startCol.value());
LM's avatar
LM committed
221 222
    }

Don Gagne's avatar
Don Gagne committed
223
    EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index rowId, Index colId) const
LM's avatar
LM committed
224
    {
Don Gagne's avatar
Don Gagne committed
225
      return m_xpr.coeff(rowId + m_startRow.value(), colId + m_startCol.value());
LM's avatar
LM committed
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    }

    inline Scalar& coeffRef(Index index)
    {
      EIGEN_STATIC_ASSERT_LVALUE(XprType)
      return m_xpr.const_cast_derived()
             .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
                       m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
    }

    inline const Scalar& coeffRef(Index index) const
    {
      return m_xpr.const_cast_derived()
             .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
                       m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
    }

    inline const CoeffReturnType coeff(Index index) const
    {
      return m_xpr
             .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
                    m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
    }

    template<int LoadMode>
Don Gagne's avatar
Don Gagne committed
251
    inline PacketScalar packet(Index rowId, Index colId) const
LM's avatar
LM committed
252 253
    {
      return m_xpr.template packet<Unaligned>
Don Gagne's avatar
Don Gagne committed
254
              (rowId + m_startRow.value(), colId + m_startCol.value());
LM's avatar
LM committed
255 256 257
    }

    template<int LoadMode>
Don Gagne's avatar
Don Gagne committed
258
    inline void writePacket(Index rowId, Index colId, const PacketScalar& val)
LM's avatar
LM committed
259 260
    {
      m_xpr.const_cast_derived().template writePacket<Unaligned>
Don Gagne's avatar
Don Gagne committed
261
              (rowId + m_startRow.value(), colId + m_startCol.value(), val);
LM's avatar
LM committed
262 263 264 265 266 267 268 269 270 271 272
    }

    template<int LoadMode>
    inline PacketScalar packet(Index index) const
    {
      return m_xpr.template packet<Unaligned>
              (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
               m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
    }

    template<int LoadMode>
Don Gagne's avatar
Don Gagne committed
273
    inline void writePacket(Index index, const PacketScalar& val)
LM's avatar
LM committed
274 275 276
    {
      m_xpr.const_cast_derived().template writePacket<Unaligned>
         (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
Don Gagne's avatar
Don Gagne committed
277
          m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), val);
LM's avatar
LM committed
278 279 280 281 282 283 284 285 286
    }

    #ifdef EIGEN_PARSED_BY_DOXYGEN
    /** \sa MapBase::data() */
    inline const Scalar* data() const;
    inline Index innerStride() const;
    inline Index outerStride() const;
    #endif

Don Gagne's avatar
Don Gagne committed
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
    const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 
    { 
      return m_xpr; 
    }
      
    Index startRow() const 
    { 
      return m_startRow.value(); 
    }
      
    Index startCol() const 
    { 
      return m_startCol.value(); 
    }

LM's avatar
LM committed
302 303 304 305 306 307 308 309 310
  protected:

    const typename XprType::Nested m_xpr;
    const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
    const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
    const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
    const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
};

Don Gagne's avatar
Don Gagne committed
311
/** \internal Internal implementation of dense Blocks in the direct access case.*/
LM's avatar
LM committed
312
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
Don Gagne's avatar
Don Gagne committed
313 314
class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
  : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >
LM's avatar
LM committed
315
{
Don Gagne's avatar
Don Gagne committed
316
    typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
LM's avatar
LM committed
317 318
  public:

Don Gagne's avatar
Don Gagne committed
319 320 321
    typedef MapBase<BlockType> Base;
    EIGEN_DENSE_PUBLIC_INTERFACE(BlockType)
    EIGEN_INHERIT_ASSIGNMENT_OPERATORS(BlockImpl_dense)
LM's avatar
LM committed
322 323 324

    /** Column or Row constructor
      */
Don Gagne's avatar
Don Gagne committed
325
    inline BlockImpl_dense(XprType& xpr, Index i)
LM's avatar
LM committed
326 327 328 329 330 331 332 333 334 335 336 337
      : Base(internal::const_cast_ptr(&xpr.coeffRef(
              (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
              (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
             BlockRows==1 ? 1 : xpr.rows(),
             BlockCols==1 ? 1 : xpr.cols()),
        m_xpr(xpr)
    {
      init();
    }

    /** Fixed-size constructor
      */
Don Gagne's avatar
Don Gagne committed
338
    inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
LM's avatar
LM committed
339 340 341 342 343 344 345
      : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
    {
      init();
    }

    /** Dynamic-size constructor
      */
Don Gagne's avatar
Don Gagne committed
346
    inline BlockImpl_dense(XprType& xpr,
LM's avatar
LM committed
347 348 349 350 351 352 353 354
          Index startRow, Index startCol,
          Index blockRows, Index blockCols)
      : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
        m_xpr(xpr)
    {
      init();
    }

Don Gagne's avatar
Don Gagne committed
355 356 357 358 359
    const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 
    { 
      return m_xpr; 
    }
      
LM's avatar
LM committed
360 361 362
    /** \sa MapBase::innerStride() */
    inline Index innerStride() const
    {
Don Gagne's avatar
Don Gagne committed
363
      return internal::traits<BlockType>::HasSameStorageOrderAsXprType
LM's avatar
LM committed
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
             ? m_xpr.innerStride()
             : m_xpr.outerStride();
    }

    /** \sa MapBase::outerStride() */
    inline Index outerStride() const
    {
      return m_outerStride;
    }

  #ifndef __SUNPRO_CC
  // FIXME sunstudio is not friendly with the above friend...
  // META-FIXME there is no 'friend' keyword around here. Is this obsolete?
  protected:
  #endif

    #ifndef EIGEN_PARSED_BY_DOXYGEN
    /** \internal used by allowAligned() */
Don Gagne's avatar
Don Gagne committed
382
    inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
LM's avatar
LM committed
383 384 385 386 387 388 389 390 391
      : Base(data, blockRows, blockCols), m_xpr(xpr)
    {
      init();
    }
    #endif

  protected:
    void init()
    {
Don Gagne's avatar
Don Gagne committed
392
      m_outerStride = internal::traits<BlockType>::HasSameStorageOrderAsXprType
LM's avatar
LM committed
393 394 395 396
                    ? m_xpr.outerStride()
                    : m_xpr.innerStride();
    }

Don Gagne's avatar
Don Gagne committed
397 398
    typename XprType::Nested m_xpr;
    Index m_outerStride;
LM's avatar
LM committed
399 400
};

Don Gagne's avatar
Don Gagne committed
401 402 403
} // end namespace internal

} // end namespace Eigen
LM's avatar
LM committed
404 405

#endif // EIGEN_BLOCK_H