Block.h 15.9 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
{
  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,
69 70 71
    IsDense = is_same<StorageKind,Dense>::value,
    IsRowMajor = (IsDense&&MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
               : (IsDense&&MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
LM's avatar
LM committed
72 73 74 75 76 77 78 79 80 81 82 83
               : 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
84
    MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
85
    FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1 || (InnerPanel && (traits<XprType>::Flags&LinearAccessBit))) ? LinearAccessBit : 0,
LM's avatar
LM committed
86 87 88 89 90 91 92 93 94 95
    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
96 97 98 99
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
100

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

Don Gagne's avatar
Don Gagne committed
103 104 105 106 107 108 109 110 111 112
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
113 114
    /** Column or Row constructor
      */
Don Gagne's avatar
Don Gagne committed
115
    inline Block(XprType& xpr, Index i) : Impl(xpr,i)
LM's avatar
LM committed
116 117 118 119 120 121 122 123
    {
      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
124 125
    inline Block(XprType& xpr, Index a_startRow, Index a_startCol)
      : Impl(xpr, a_startRow, a_startCol)
LM's avatar
LM committed
126 127
    {
      EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
Don Gagne's avatar
Don Gagne committed
128 129
      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
130 131 132 133 134
    }

    /** Dynamic-size constructor
      */
    inline Block(XprType& xpr,
Don Gagne's avatar
Don Gagne committed
135
          Index a_startRow, Index a_startCol,
LM's avatar
LM committed
136
          Index blockRows, Index blockCols)
Don Gagne's avatar
Don Gagne committed
137
      : Impl(xpr, a_startRow, a_startCol, blockRows, blockCols)
LM's avatar
LM committed
138 139 140
    {
      eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
          && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
Don Gagne's avatar
Don Gagne committed
141 142
      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
143
    }
Don Gagne's avatar
Don Gagne committed
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
};
         
// 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
162

Don Gagne's avatar
Don Gagne committed
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 206
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
207 208 209 210

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

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

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

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

    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
252
    inline PacketScalar packet(Index rowId, Index colId) const
LM's avatar
LM committed
253 254
    {
      return m_xpr.template packet<Unaligned>
Don Gagne's avatar
Don Gagne committed
255
              (rowId + m_startRow.value(), colId + m_startCol.value());
LM's avatar
LM committed
256 257 258
    }

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

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

    #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
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    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
303 304 305 306 307 308 309 310 311
  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
312
/** \internal Internal implementation of dense Blocks in the direct access case.*/
LM's avatar
LM committed
313
template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
Don Gagne's avatar
Don Gagne committed
314 315
class BlockImpl_dense<XprType,BlockRows,BlockCols, InnerPanel,true>
  : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel> >
LM's avatar
LM committed
316
{
Don Gagne's avatar
Don Gagne committed
317
    typedef Block<XprType, BlockRows, BlockCols, InnerPanel> BlockType;
LM's avatar
LM committed
318 319
  public:

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

    /** Column or Row constructor
      */
Don Gagne's avatar
Don Gagne committed
326
    inline BlockImpl_dense(XprType& xpr, Index i)
LM's avatar
LM committed
327 328 329 330 331 332 333 334 335 336 337 338
      : 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
339
    inline BlockImpl_dense(XprType& xpr, Index startRow, Index startCol)
LM's avatar
LM committed
340 341 342 343 344 345 346
      : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
    {
      init();
    }

    /** Dynamic-size constructor
      */
Don Gagne's avatar
Don Gagne committed
347
    inline BlockImpl_dense(XprType& xpr,
LM's avatar
LM committed
348 349 350 351 352 353 354 355
          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
356 357 358 359 360
    const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 
    { 
      return m_xpr; 
    }
      
LM's avatar
LM committed
361 362 363
    /** \sa MapBase::innerStride() */
    inline Index innerStride() const
    {
Don Gagne's avatar
Don Gagne committed
364
      return internal::traits<BlockType>::HasSameStorageOrderAsXprType
LM's avatar
LM committed
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
             ? 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
383
    inline BlockImpl_dense(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
LM's avatar
LM committed
384 385 386 387 388 389 390 391 392
      : Base(data, blockRows, blockCols), m_xpr(xpr)
    {
      init();
    }
    #endif

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

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

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

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

#endif // EIGEN_BLOCK_H