mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-04-06 19:10:36 +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.
|
||||
*
|
||||
* The coefficients of the product will be computed as requested that is particularly useful when you
|
||||
* only want to compute a small fraction of the result's coefficients.
|
||||
* Here is an example:
|
||||
* \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
|
||||
* The returned product will behave like any other expressions: the coefficients of the product will be
|
||||
* computed once at a time as requested. This might be useful in some extremely rare cases when only
|
||||
* a small and no coherent fraction of the result's coefficients have to be computed.
|
||||
*
|
||||
* \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&)
|
||||
*/
|
||||
|
@ -83,6 +83,9 @@ class ProductBase : public MatrixBase<Derived>
|
||||
typedef typename RhsBlasTraits::DirectLinearAccessType 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:
|
||||
|
||||
typedef typename Base::PlainMatrixType PlainMatrixType;
|
||||
@ -121,6 +124,16 @@ class ProductBase : public MatrixBase<Derived>
|
||||
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:
|
||||
|
||||
const LhsNested m_lhs;
|
||||
|
@ -127,8 +127,14 @@ class CoeffBasedProduct
|
||||
Unroll ? InnerSize-1 : Dynamic,
|
||||
_LhsNested, _RhsNested, Scalar> ScalarCoeffImpl;
|
||||
|
||||
typedef CoeffBasedProduct<LhsNested,RhsNested,NestByRefBit> LazyCoeffBasedProductType;
|
||||
|
||||
public:
|
||||
|
||||
inline CoeffBasedProduct(const CoeffBasedProduct& other)
|
||||
: Base(), m_lhs(other.m_lhs), m_rhs(other.m_rhs)
|
||||
{}
|
||||
|
||||
template<typename Lhs, typename Rhs>
|
||||
inline CoeffBasedProduct(const Lhs& lhs, const Rhs& rhs)
|
||||
: m_lhs(lhs), m_rhs(rhs)
|
||||
@ -185,6 +191,16 @@ class CoeffBasedProduct
|
||||
const _LhsNested& lhs() const { return m_lhs; }
|
||||
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:
|
||||
const LhsNested m_lhs;
|
||||
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());
|
||||
\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
|
||||
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:
|
||||
@ -92,6 +92,10 @@ MatrixXf a, b, c;
|
||||
...
|
||||
c.noalias() += 2 * a.transpose() * b;
|
||||
\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