diff options
author | Gael Guennebaud <g.gael@free.fr> | 2008-06-15 11:54:18 +0000 |
---|---|---|
committer | Gael Guennebaud <g.gael@free.fr> | 2008-06-15 11:54:18 +0000 |
commit | 0ee6b08128de893150d7d2d07081bf33b4cb9fb1 (patch) | |
tree | 1d22a187485c99fb9f280d1824dab59c9c1ea06f /Eigen/src/Core | |
parent | fbbd8afe3086cc1a1f455cc5264f0b6fc063f8b6 (diff) |
* split Product to a DiagonalProduct template specialization
to optimize matrix-diag and diag-matrix products without
making Product over complicated.
* compilation fixes in Tridiagonalization and HessenbergDecomposition
in the case of 2x2 matrices.
* added an Orientation2D small class with similar interface than Quaternion
(used by Transform to handle 2D and 3D orientations seamlessly)
* added a couple of features in Transform.
Diffstat (limited to 'Eigen/src/Core')
-rw-r--r-- | Eigen/src/Core/DiagonalProduct.h | 108 | ||||
-rw-r--r-- | Eigen/src/Core/Product.h | 58 | ||||
-rw-r--r-- | Eigen/src/Core/Transpose.h | 2 | ||||
-rw-r--r-- | Eigen/src/Core/util/Constants.h | 4 |
4 files changed, 130 insertions, 42 deletions
diff --git a/Eigen/src/Core/DiagonalProduct.h b/Eigen/src/Core/DiagonalProduct.h new file mode 100644 index 000000000..5663942ff --- /dev/null +++ b/Eigen/src/Core/DiagonalProduct.h @@ -0,0 +1,108 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. Eigen itself is part of the KDE project. +// +// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr> +// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr> +// +// Eigen is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 3 of the License, or (at your option) any later version. +// +// Alternatively, you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 2 of +// the License, or (at your option) any later version. +// +// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License and a copy of the GNU General Public License along with +// Eigen. If not, see <http://www.gnu.org/licenses/>. + +#ifndef EIGEN_DIAGONALPRODUCT_H +#define EIGEN_DIAGONALPRODUCT_H + +template<typename Lhs, typename Rhs> +struct ei_traits<Product<Lhs, Rhs, DiagonalProduct> > +{ + typedef typename Lhs::Scalar Scalar; + typedef typename ei_nested<Lhs>::type LhsNested; + typedef typename ei_nested<Rhs>::type RhsNested; + typedef typename ei_unref<LhsNested>::type _LhsNested; + typedef typename ei_unref<RhsNested>::type _RhsNested; + enum { + LhsFlags = _LhsNested::Flags, + RhsFlags = _RhsNested::Flags, + RowsAtCompileTime = Lhs::RowsAtCompileTime, + ColsAtCompileTime = Rhs::ColsAtCompileTime, + MaxRowsAtCompileTime = Lhs::MaxRowsAtCompileTime, + MaxColsAtCompileTime = Rhs::MaxColsAtCompileTime, + _RhsVectorizable = (RhsFlags & RowMajorBit) && (RhsFlags & VectorizableBit) + && (ColsAtCompileTime % ei_packet_traits<Scalar>::size == 0), + _LhsVectorizable = (!(LhsFlags & RowMajorBit)) && (LhsFlags & VectorizableBit) + && (RowsAtCompileTime % ei_packet_traits<Scalar>::size == 0), + _LostBits = ~(((RhsFlags & RowMajorBit) && (!_LhsVectorizable) ? 0 : RowMajorBit) + | ((RowsAtCompileTime == Dynamic || ColsAtCompileTime == Dynamic) ? 0 : LargeBit)), + Flags = ((unsigned int)(LhsFlags | RhsFlags) & HereditaryBits & _LostBits) + | (_LhsVectorizable || _RhsVectorizable ? VectorizableBit : 0), + CoeffReadCost = NumTraits<Scalar>::MulCost + _LhsNested::CoeffReadCost + _RhsNested::CoeffReadCost + }; +}; + +template<typename Lhs, typename Rhs> class Product<Lhs, Rhs, DiagonalProduct> : ei_no_assignment_operator, + public MatrixBase<Product<Lhs, Rhs, DiagonalProduct> > +{ + public: + + EIGEN_GENERIC_PUBLIC_INTERFACE(Product) + typedef typename ei_traits<Product>::LhsNested LhsNested; + typedef typename ei_traits<Product>::RhsNested RhsNested; + typedef typename ei_traits<Product>::_LhsNested _LhsNested; + typedef typename ei_traits<Product>::_RhsNested _RhsNested; + + enum { + PacketSize = ei_packet_traits<Scalar>::size + }; + + inline Product(const Lhs& lhs, const Rhs& rhs) + : m_lhs(lhs), m_rhs(rhs) + { + ei_assert(lhs.cols() == rhs.rows()); + } + + private: + + inline int _rows() const { return m_lhs.rows(); } + inline int _cols() const { return m_rhs.cols(); } + + const Scalar _coeff(int row, int col) const + { + int unique = ((Rhs::Flags&Diagonal)==Diagonal) ? col : row; + return m_lhs.coeff(row, unique) * m_rhs.coeff(unique, col); + } + + template<int LoadMode> + const PacketScalar _packetCoeff(int row, int col) const + { + if ((Rhs::Flags&Diagonal)==Diagonal) + { + ei_assert((_LhsNested::Flags&RowMajorBit)==0); + return ei_pmul(m_lhs.template packetCoeff<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col))); + } + else + { + ei_assert(_RhsNested::Flags&RowMajorBit); + return ei_pmul(ei_pset1(m_lhs.coeff(row, row)), m_rhs.template packetCoeff<LoadMode>(row, col)); + } + } + + protected: + const LhsNested m_lhs; + const RhsNested m_rhs; +}; + +#endif // EIGEN_DIAGONALPRODUCT_H diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h index 6c653a558..6875e3158 100644 --- a/Eigen/src/Core/Product.h +++ b/Eigen/src/Core/Product.h @@ -144,11 +144,12 @@ struct ei_packet_product_impl<false, Index, Dynamic, Lhs, Rhs, PacketScalar> */ template<typename Lhs, typename Rhs> struct ei_product_eval_mode { - enum{ value = Lhs::MaxRowsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD - && Rhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD - && Lhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD - && (Rhs::Flags&Diagonal)!=Diagonal - ? CacheFriendlyProduct : NormalProduct }; + enum{ value = ((Rhs::Flags&Diagonal)==Diagonal) || ((Lhs::Flags&Diagonal)==Diagonal) + ? DiagonalProduct + : Lhs::MaxRowsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD + && Rhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD + && Lhs::MaxColsAtCompileTime >= EIGEN_CACHEFRIENDLY_PRODUCT_THRESHOLD + ? CacheFriendlyProduct : NormalProduct }; }; template<typename T> class ei_product_eval_to_column_major @@ -265,44 +266,25 @@ template<typename Lhs, typename Rhs, int EvalMode> class Product : ei_no_assignm const Scalar _coeff(int row, int col) const { - if ((Rhs::Flags&Diagonal)==Diagonal) - { - return m_lhs.coeff(row, col) * m_rhs.coeff(col, col); - } - else if ((Lhs::Flags&Diagonal)==Diagonal) - { - return m_lhs.coeff(row, row) * m_rhs.coeff(row, col); - } - else - { - Scalar res; - const bool unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT; - ei_product_impl<unroll ? Lhs::ColsAtCompileTime-1 : Dynamic, - unroll ? Lhs::ColsAtCompileTime : Dynamic, - _LhsNested, _RhsNested> - ::run(row, col, m_lhs, m_rhs, res); - return res; - } + Scalar res; + const bool unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT; + ei_product_impl<unroll ? Lhs::ColsAtCompileTime-1 : Dynamic, + unroll ? Lhs::ColsAtCompileTime : Dynamic, + _LhsNested, _RhsNested> + ::run(row, col, m_lhs, m_rhs, res); + return res; } template<int LoadMode> const PacketScalar _packetCoeff(int row, int col) const { - if ((Rhs::Flags&Diagonal)==Diagonal) - { - ei_assert((_LhsNested::Flags&RowMajorBit)==0); - return ei_pmul(m_lhs.template packetCoeff<LoadMode>(row, col), ei_pset1(m_rhs.coeff(col, col))); - } - else - { - const bool unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT; - PacketScalar res; - ei_packet_product_impl<Flags&RowMajorBit ? true : false, Lhs::ColsAtCompileTime-1, - unroll ? Lhs::ColsAtCompileTime : Dynamic, - _LhsNested, _RhsNested, PacketScalar> - ::run(row, col, m_lhs, m_rhs, res); - return res; - } + const bool unroll = CoeffReadCost <= EIGEN_UNROLLING_LIMIT; + PacketScalar res; + ei_packet_product_impl<Flags&RowMajorBit ? true : false, Lhs::ColsAtCompileTime-1, + unroll ? Lhs::ColsAtCompileTime : Dynamic, + _LhsNested, _RhsNested, PacketScalar> + ::run(row, col, m_lhs, m_rhs, res); + return res; } template<typename Lhs_, typename Rhs_, int EvalMode_, typename DestDerived_, bool DirectAccess_> diff --git a/Eigen/src/Core/Transpose.h b/Eigen/src/Core/Transpose.h index 1a4843973..23749d67c 100644 --- a/Eigen/src/Core/Transpose.h +++ b/Eigen/src/Core/Transpose.h @@ -52,8 +52,6 @@ struct ei_traits<Transpose<MatrixType> > & ~( Like1DArrayBit | LowerTriangularBit | UpperTriangularBit) | (int(_MatrixTypeNested::Flags)&UpperTriangularBit ? LowerTriangularBit : 0) | (int(_MatrixTypeNested::Flags)&LowerTriangularBit ? UpperTriangularBit : 0), - // Note that the above test cannot be simplified using ^ because a diagonal matrix - // has both LowerTriangularBit and UpperTriangularBit and both must be preserved. CoeffReadCost = _MatrixTypeNested::CoeffReadCost }; }; diff --git a/Eigen/src/Core/util/Constants.h b/Eigen/src/Core/util/Constants.h index fdde9acd3..163832394 100644 --- a/Eigen/src/Core/util/Constants.h +++ b/Eigen/src/Core/util/Constants.h @@ -80,7 +80,7 @@ const unsigned int Like1DArrayBit = 0x20; /** \ingroup flags * * means all diagonal coefficients are equal to 0 */ -const unsigned int ZeroDiagBit = 0x40; +const unsigned int ZeroDiagBit = 0x40; /** \ingroup flags * @@ -140,7 +140,7 @@ enum { Aligned=0, UnAligned=1 }; enum { ConditionalJumpCost = 5 }; enum CornerType { TopLeft, TopRight, BottomLeft, BottomRight }; enum DirectionType { Vertical, Horizontal }; -enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, LazyProduct}; +enum ProductEvaluationMode { NormalProduct, CacheFriendlyProduct, DiagonalProduct, LazyProduct}; #endif // EIGEN_CONSTANTS_H |