Block.h
Go to the documentation of this file.
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 // Copyright (C) 2006-2010 Benoit Jacob <jacob.benoit.1@gmail.com>
00006 //
00007 // Eigen is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public
00009 // License as published by the Free Software Foundation; either
00010 // version 3 of the License, or (at your option) any later version.
00011 //
00012 // Alternatively, you can redistribute it and/or
00013 // modify it under the terms of the GNU General Public License as
00014 // published by the Free Software Foundation; either version 2 of
00015 // the License, or (at your option) any later version.
00016 //
00017 // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
00018 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00019 // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
00020 // GNU General Public License for more details.
00021 //
00022 // You should have received a copy of the GNU Lesser General Public
00023 // License and a copy of the GNU General Public License along with
00024 // Eigen. If not, see <http://www.gnu.org/licenses/>.
00025 
00026 #ifndef EIGEN_BLOCK_H
00027 #define EIGEN_BLOCK_H
00028 
00029 namespace Eigen { 
00030 
00064 namespace internal {
00065 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess>
00066 struct traits<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> > : traits<XprType>
00067 {
00068   typedef typename traits<XprType>::Scalar Scalar;
00069   typedef typename traits<XprType>::StorageKind StorageKind;
00070   typedef typename traits<XprType>::XprKind XprKind;
00071   typedef typename nested<XprType>::type XprTypeNested;
00072   typedef typename remove_reference<XprTypeNested>::type _XprTypeNested;
00073   enum{
00074     MatrixRows = traits<XprType>::RowsAtCompileTime,
00075     MatrixCols = traits<XprType>::ColsAtCompileTime,
00076     RowsAtCompileTime = MatrixRows == 0 ? 0 : BlockRows,
00077     ColsAtCompileTime = MatrixCols == 0 ? 0 : BlockCols,
00078     MaxRowsAtCompileTime = BlockRows==0 ? 0
00079                          : RowsAtCompileTime != Dynamic ? int(RowsAtCompileTime)
00080                          : int(traits<XprType>::MaxRowsAtCompileTime),
00081     MaxColsAtCompileTime = BlockCols==0 ? 0
00082                          : ColsAtCompileTime != Dynamic ? int(ColsAtCompileTime)
00083                          : int(traits<XprType>::MaxColsAtCompileTime),
00084     XprTypeIsRowMajor = (int(traits<XprType>::Flags)&RowMajorBit) != 0,
00085     IsRowMajor = (MaxRowsAtCompileTime==1&&MaxColsAtCompileTime!=1) ? 1
00086                : (MaxColsAtCompileTime==1&&MaxRowsAtCompileTime!=1) ? 0
00087                : XprTypeIsRowMajor,
00088     HasSameStorageOrderAsXprType = (IsRowMajor == XprTypeIsRowMajor),
00089     InnerSize = IsRowMajor ? int(ColsAtCompileTime) : int(RowsAtCompileTime),
00090     InnerStrideAtCompileTime = HasSameStorageOrderAsXprType
00091                              ? int(inner_stride_at_compile_time<XprType>::ret)
00092                              : int(outer_stride_at_compile_time<XprType>::ret),
00093     OuterStrideAtCompileTime = HasSameStorageOrderAsXprType
00094                              ? int(outer_stride_at_compile_time<XprType>::ret)
00095                              : int(inner_stride_at_compile_time<XprType>::ret),
00096     MaskPacketAccessBit = (InnerSize == Dynamic || (InnerSize % packet_traits<Scalar>::size) == 0)
00097                        && (InnerStrideAtCompileTime == 1)
00098                         ? PacketAccessBit : 0,
00099     MaskAlignedBit = (InnerPanel && (OuterStrideAtCompileTime!=Dynamic) && (((OuterStrideAtCompileTime * int(sizeof(Scalar))) % 16) == 0)) ? AlignedBit : 0,
00100     FlagsLinearAccessBit = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? LinearAccessBit : 0,
00101     FlagsLvalueBit = is_lvalue<XprType>::value ? LvalueBit : 0,
00102     FlagsRowMajorBit = IsRowMajor ? RowMajorBit : 0,
00103     Flags0 = traits<XprType>::Flags & ( (HereditaryBits & ~RowMajorBit) |
00104                                         DirectAccessBit |
00105                                         MaskPacketAccessBit |
00106                                         MaskAlignedBit),
00107     Flags = Flags0 | FlagsLinearAccessBit | FlagsLvalueBit | FlagsRowMajorBit
00108   };
00109 };
00110 }
00111 
00112 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel, bool HasDirectAccess> class Block
00113   : public internal::dense_xpr_base<Block<XprType, BlockRows, BlockCols, InnerPanel, HasDirectAccess> >::type
00114 {
00115   public:
00116 
00117     typedef typename internal::dense_xpr_base<Block>::type Base;
00118     EIGEN_DENSE_PUBLIC_INTERFACE(Block)
00119 
00120     class InnerIterator;
00121 
00124     inline Block(XprType& xpr, Index i)
00125       : m_xpr(xpr),
00126         // It is a row if and only if BlockRows==1 and BlockCols==XprType::ColsAtCompileTime,
00127         // and it is a column if and only if BlockRows==XprType::RowsAtCompileTime and BlockCols==1,
00128         // all other cases are invalid.
00129         // The case a 1x1 matrix seems ambiguous, but the result is the same anyway.
00130         m_startRow( (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0),
00131         m_startCol( (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0),
00132         m_blockRows(BlockRows==1 ? 1 : xpr.rows()),
00133         m_blockCols(BlockCols==1 ? 1 : xpr.cols())
00134     {
00135       eigen_assert( (i>=0) && (
00136           ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
00137         ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
00138     }
00139 
00142     inline Block(XprType& xpr, Index startRow, Index startCol)
00143       : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
00144         m_blockRows(BlockRows), m_blockCols(BlockCols)
00145     {
00146       EIGEN_STATIC_ASSERT(RowsAtCompileTime!=Dynamic && ColsAtCompileTime!=Dynamic,THIS_METHOD_IS_ONLY_FOR_FIXED_SIZE)
00147       eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
00148              && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
00149     }
00150 
00153     inline Block(XprType& xpr,
00154           Index startRow, Index startCol,
00155           Index blockRows, Index blockCols)
00156       : m_xpr(xpr), m_startRow(startRow), m_startCol(startCol),
00157                           m_blockRows(blockRows), m_blockCols(blockCols)
00158     {
00159       eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
00160           && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
00161       eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
00162           && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
00163     }
00164 
00165     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
00166 
00167     inline Index rows() const { return m_blockRows.value(); }
00168     inline Index cols() const { return m_blockCols.value(); }
00169 
00170     inline Scalar& coeffRef(Index row, Index col)
00171     {
00172       EIGEN_STATIC_ASSERT_LVALUE(XprType)
00173       return m_xpr.const_cast_derived()
00174                .coeffRef(row + m_startRow.value(), col + m_startCol.value());
00175     }
00176 
00177     inline const Scalar& coeffRef(Index row, Index col) const
00178     {
00179       return m_xpr.derived()
00180                .coeffRef(row + m_startRow.value(), col + m_startCol.value());
00181     }
00182 
00183     EIGEN_STRONG_INLINE const CoeffReturnType coeff(Index row, Index col) const
00184     {
00185       return m_xpr.coeff(row + m_startRow.value(), col + m_startCol.value());
00186     }
00187 
00188     inline Scalar& coeffRef(Index index)
00189     {
00190       EIGEN_STATIC_ASSERT_LVALUE(XprType)
00191       return m_xpr.const_cast_derived()
00192              .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
00193                        m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
00194     }
00195 
00196     inline const Scalar& coeffRef(Index index) const
00197     {
00198       return m_xpr.const_cast_derived()
00199              .coeffRef(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
00200                        m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
00201     }
00202 
00203     inline const CoeffReturnType coeff(Index index) const
00204     {
00205       return m_xpr
00206              .coeff(m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
00207                     m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
00208     }
00209 
00210     template<int LoadMode>
00211     inline PacketScalar packet(Index row, Index col) const
00212     {
00213       return m_xpr.template packet<Unaligned>
00214               (row + m_startRow.value(), col + m_startCol.value());
00215     }
00216 
00217     template<int LoadMode>
00218     inline void writePacket(Index row, Index col, const PacketScalar& x)
00219     {
00220       m_xpr.const_cast_derived().template writePacket<Unaligned>
00221               (row + m_startRow.value(), col + m_startCol.value(), x);
00222     }
00223 
00224     template<int LoadMode>
00225     inline PacketScalar packet(Index index) const
00226     {
00227       return m_xpr.template packet<Unaligned>
00228               (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
00229                m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0));
00230     }
00231 
00232     template<int LoadMode>
00233     inline void writePacket(Index index, const PacketScalar& x)
00234     {
00235       m_xpr.const_cast_derived().template writePacket<Unaligned>
00236          (m_startRow.value() + (RowsAtCompileTime == 1 ? 0 : index),
00237           m_startCol.value() + (RowsAtCompileTime == 1 ? index : 0), x);
00238     }
00239 
00240     #ifdef EIGEN_PARSED_BY_DOXYGEN
00241 
00242     inline const Scalar* data() const;
00243     inline Index innerStride() const;
00244     inline Index outerStride() const;
00245     #endif
00246 
00247     const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 
00248     { 
00249       return m_xpr; 
00250     }
00251       
00252     Index startRow() const 
00253     { 
00254       return m_startRow.value(); 
00255     }
00256       
00257     Index startCol() const 
00258     { 
00259       return m_startCol.value(); 
00260     }
00261 
00262   protected:
00263 
00264     const typename XprType::Nested m_xpr;
00265     const internal::variable_if_dynamic<Index, XprType::RowsAtCompileTime == 1 ? 0 : Dynamic> m_startRow;
00266     const internal::variable_if_dynamic<Index, XprType::ColsAtCompileTime == 1 ? 0 : Dynamic> m_startCol;
00267     const internal::variable_if_dynamic<Index, RowsAtCompileTime> m_blockRows;
00268     const internal::variable_if_dynamic<Index, ColsAtCompileTime> m_blockCols;
00269 };
00270 
00272 template<typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
00273 class Block<XprType,BlockRows,BlockCols, InnerPanel,true>
00274   : public MapBase<Block<XprType, BlockRows, BlockCols, InnerPanel, true> >
00275 {
00276   public:
00277 
00278     typedef MapBase<Block> Base;
00279     EIGEN_DENSE_PUBLIC_INTERFACE(Block)
00280 
00281     EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Block)
00282 
00285     inline Block(XprType& xpr, Index i)
00286       : Base(internal::const_cast_ptr(&xpr.coeffRef(
00287               (BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) ? i : 0,
00288               (BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) ? i : 0)),
00289              BlockRows==1 ? 1 : xpr.rows(),
00290              BlockCols==1 ? 1 : xpr.cols()),
00291         m_xpr(xpr)
00292     {
00293       eigen_assert( (i>=0) && (
00294           ((BlockRows==1) && (BlockCols==XprType::ColsAtCompileTime) && i<xpr.rows())
00295         ||((BlockRows==XprType::RowsAtCompileTime) && (BlockCols==1) && i<xpr.cols())));
00296       init();
00297     }
00298 
00301     inline Block(XprType& xpr, Index startRow, Index startCol)
00302       : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol))), m_xpr(xpr)
00303     {
00304       eigen_assert(startRow >= 0 && BlockRows >= 1 && startRow + BlockRows <= xpr.rows()
00305              && startCol >= 0 && BlockCols >= 1 && startCol + BlockCols <= xpr.cols());
00306       init();
00307     }
00308 
00311     inline Block(XprType& xpr,
00312           Index startRow, Index startCol,
00313           Index blockRows, Index blockCols)
00314       : Base(internal::const_cast_ptr(&xpr.coeffRef(startRow,startCol)), blockRows, blockCols),
00315         m_xpr(xpr)
00316     {
00317       eigen_assert((RowsAtCompileTime==Dynamic || RowsAtCompileTime==blockRows)
00318              && (ColsAtCompileTime==Dynamic || ColsAtCompileTime==blockCols));
00319       eigen_assert(startRow >= 0 && blockRows >= 0 && startRow + blockRows <= xpr.rows()
00320              && startCol >= 0 && blockCols >= 0 && startCol + blockCols <= xpr.cols());
00321       init();
00322     }
00323 
00324     const typename internal::remove_all<typename XprType::Nested>::type& nestedExpression() const 
00325     { 
00326       return m_xpr; 
00327     }
00328       
00330     inline Index innerStride() const
00331     {
00332       return internal::traits<Block>::HasSameStorageOrderAsXprType
00333              ? m_xpr.innerStride()
00334              : m_xpr.outerStride();
00335     }
00336 
00338     inline Index outerStride() const
00339     {
00340       return m_outerStride;
00341     }
00342 
00343   #ifndef __SUNPRO_CC
00344   // FIXME sunstudio is not friendly with the above friend...
00345   // META-FIXME there is no 'friend' keyword around here. Is this obsolete?
00346   protected:
00347   #endif
00348 
00349     #ifndef EIGEN_PARSED_BY_DOXYGEN
00350 
00351     inline Block(XprType& xpr, const Scalar* data, Index blockRows, Index blockCols)
00352       : Base(data, blockRows, blockCols), m_xpr(xpr)
00353     {
00354       init();
00355     }
00356     #endif
00357 
00358   protected:
00359     void init()
00360     {
00361       m_outerStride = internal::traits<Block>::HasSameStorageOrderAsXprType
00362                     ? m_xpr.outerStride()
00363                     : m_xpr.innerStride();
00364     }
00365 
00366     typename XprType::Nested m_xpr;
00367     Index m_outerStride;
00368 };
00369 
00370 } // end namespace Eigen
00371 
00372 #endif // EIGEN_BLOCK_H