mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-06-04 18:54:00 +08:00
finally here is a simple solution making (a*b).diagonal() even faster than a.lazyProduct(b).diagonal() !!
This commit is contained in:
parent
71b64d3498
commit
0ca67afe6a
@ -447,17 +447,12 @@ MatrixBase<Derived>::operator*(const MatrixBase<OtherDerived> &other) const
|
|||||||
|
|
||||||
/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation.
|
/** \returns an expression of the matrix product of \c *this and \a other without implicit evaluation.
|
||||||
*
|
*
|
||||||
* The coefficients of the product will be computed as requested that is particularly useful when you
|
* The returned product will behave like any other expressions: the coefficients of the product will be
|
||||||
* only want to compute a small fraction of the result's coefficients.
|
* computed once at a time as requested. This might be useful in some extremely rare cases when only
|
||||||
* Here is an example:
|
* a small and no coherent fraction of the result's coefficients have to be computed.
|
||||||
* \code
|
|
||||||
* MatrixXf a(10,10), b(10,10);
|
|
||||||
* (a*b).diagonal().sum(); // here a*b is entirely computed into a 10x10 temporary matrix
|
|
||||||
* a.lazyProduct(b).diagonal().sum(); // here a*b is evaluated in a lazy manner,
|
|
||||||
* // so only the diagonal coefficients will be computed
|
|
||||||
* \endcode
|
|
||||||
*
|
*
|
||||||
* \warning This version of the matrix product can be much much slower if all coefficients have to be computed anyways.
|
* \warning This version of the matrix product can be much much slower. So use it only if you know
|
||||||
|
* what you are doing and that you measured a true speed improvement.
|
||||||
*
|
*
|
||||||
* \sa operator*(const MatrixBase&)
|
* \sa operator*(const MatrixBase&)
|
||||||
*/
|
*/
|
||||||
|
@ -83,6 +83,9 @@ class ProductBase : public MatrixBase<Derived>
|
|||||||
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
typedef typename RhsBlasTraits::DirectLinearAccessType ActualRhsType;
|
||||||
typedef typename ei_cleantype<ActualRhsType>::type _ActualRhsType;
|
typedef typename ei_cleantype<ActualRhsType>::type _ActualRhsType;
|
||||||
|
|
||||||
|
// Diagonal of a product: no need to evaluate the arguments because they are going to be evaluated only once
|
||||||
|
typedef CoeffBasedProduct<LhsNested, RhsNested, 0> FullyLazyCoeffBaseProductType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef typename Base::PlainMatrixType PlainMatrixType;
|
typedef typename Base::PlainMatrixType PlainMatrixType;
|
||||||
@ -121,6 +124,16 @@ class ProductBase : public MatrixBase<Derived>
|
|||||||
return m_result;
|
return m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Diagonal<FullyLazyCoeffBaseProductType,0> diagonal() const
|
||||||
|
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
|
||||||
|
|
||||||
|
template<int Index>
|
||||||
|
const Diagonal<FullyLazyCoeffBaseProductType,Index> diagonal() const
|
||||||
|
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs); }
|
||||||
|
|
||||||
|
const Diagonal<FullyLazyCoeffBaseProductType,Dynamic> diagonal(int index) const
|
||||||
|
{ return FullyLazyCoeffBaseProductType(m_lhs, m_rhs).diagonal(index); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const LhsNested m_lhs;
|
const LhsNested m_lhs;
|
||||||
|
@ -127,8 +127,14 @@ class CoeffBasedProduct
|
|||||||
Unroll ? InnerSize-1 : Dynamic,
|
Unroll ? InnerSize-1 : Dynamic,
|
||||||
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
||||||
|
|
||||||
|
typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
inline CoeffBasedProduct(const CoeffBasedProduct& other)
|
||||||
|
: Base(), m_lhs(other.m_lhs), m_rhs(other.m_rhs)
|
||||||
|
{}
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs)
|
inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs)
|
||||||
: m_lhs(lhs), m_rhs(rhs)
|
: m_lhs(lhs), m_rhs(rhs)
|
||||||
@ -185,6 +191,16 @@ class CoeffBasedProduct
|
|||||||
const _LhsNested& lhs() const { return m_lhs; }
|
const _LhsNested& lhs() const { return m_lhs; }
|
||||||
const _RhsNested& rhs() const { return m_rhs; }
|
const _RhsNested& rhs() const { return m_rhs; }
|
||||||
|
|
||||||
|
const Diagonal<LazyCoeffBasedProductType,0> diagonal() const
|
||||||
|
{ return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); }
|
||||||
|
|
||||||
|
template<int Index>
|
||||||
|
const Diagonal<LazyCoeffBasedProductType,Index> diagonal() const
|
||||||
|
{ return reinterpret_cast<const LazyCoeffBasedProductType&>(*this); }
|
||||||
|
|
||||||
|
const Diagonal<LazyCoeffBasedProductType,Dynamic> diagonal(int index) const
|
||||||
|
{ return reinterpret_cast<const LazyCoeffBasedProductType&>(*this).diagonal(index); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const LhsNested m_lhs;
|
const LhsNested m_lhs;
|
||||||
const RhsNested m_rhs;
|
const RhsNested m_rhs;
|
||||||
|
@ -81,9 +81,9 @@ With Eigen2 you would have written:
|
|||||||
c = (a.cwise().abs().cwise().pow(3)).cwise() * (b.cwise().abs().cwise().sin());
|
c = (a.cwise().abs().cwise().pow(3)).cwise() * (b.cwise().abs().cwise().sin());
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\section LazyVsNoalias Lazy evaluation versus noalias
|
\section LazyVsNoalias Lazy evaluation and noalias
|
||||||
|
|
||||||
In Eigen all operations are performed in a lazy fashion except the matrix products which are always evaluated to a temporary by default.
|
In Eigen all operations are performed in a lazy fashion except the matrix products which are always evaluated into a temporary by default.
|
||||||
In Eigen2, lazy evaluation could be enforced by tagging a product using the .lazy() function. However, in complex expressions it was not
|
In Eigen2, lazy evaluation could be enforced by tagging a product using the .lazy() function. However, in complex expressions it was not
|
||||||
easy to determine where to put the lazy() function. In Eigen3, the lazy() feature has been superseded by the MatrixBase::noalias() function
|
easy to determine where to put the lazy() function. In Eigen3, the lazy() feature has been superseded by the MatrixBase::noalias() function
|
||||||
which can be used on the left hand side of an assignment when no aliasing can occur. Here is an example:
|
which can be used on the left hand side of an assignment when no aliasing can occur. Here is an example:
|
||||||
@ -92,6 +92,10 @@ MatrixXf a, b, c;
|
|||||||
...
|
...
|
||||||
c.noalias() += 2 * a.transpose() * b;
|
c.noalias() += 2 * a.transpose() * b;
|
||||||
\endcode
|
\endcode
|
||||||
|
However, the noalias mechanism does not cover all the features of the old .lazy(). Indeed, in some extremely rare cases,
|
||||||
|
it might be useful to explicit request for a lay product, i.e., for a product which will be evaluated one coefficient at once, on request,
|
||||||
|
just like any other expressions. To this end you can use the MatrixBase::lazyProduct() function, however we strongly discourage you to
|
||||||
|
use it unless you are sure of what you are doing, i.e., you have rigourosly measured a speed improvement.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user