aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2010-02-10 14:08:47 +0100
committerGravatar Gael Guennebaud <g.gael@free.fr>2010-02-10 14:08:47 +0100
commit0ca67afe6abbe9c19a8254d50daaddd2a343531c (patch)
treee832b7636a793c649ad947304c0369ed94167ac5
parent71b64d34987ae7d3fbe70f0098c12a7c65b41084 (diff)
finally here is a simple solution making (a*b).diagonal() even faster than a.lazyProduct(b).diagonal() !!
-rw-r--r--Eigen/src/Core/Product.h15
-rw-r--r--Eigen/src/Core/ProductBase.h13
-rw-r--r--Eigen/src/Core/products/CoeffBasedProduct.h16
-rw-r--r--doc/A05_PortingFrom2To3.dox8
4 files changed, 40 insertions, 12 deletions
diff --git a/Eigen/src/Core/Product.h b/Eigen/src/Core/Product.h
index 5903476b5..af05773ee 100644
--- a/Eigen/src/Core/Product.h
+++ b/Eigen/src/Core/Product.h
@@ -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&)
*/
diff --git a/Eigen/src/Core/ProductBase.h b/Eigen/src/Core/ProductBase.h
index bbd77f059..481e7c760 100644
--- a/Eigen/src/Core/ProductBase.h
+++ b/Eigen/src/Core/ProductBase.h
@@ -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;
diff --git a/Eigen/src/Core/products/CoeffBasedProduct.h b/Eigen/src/Core/products/CoeffBasedProduct.h
index c9d333072..f030d59b5 100644
--- a/Eigen/src/Core/products/CoeffBasedProduct.h
+++ b/Eigen/src/Core/products/CoeffBasedProduct.h
@@ -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;
diff --git a/doc/A05_PortingFrom2To3.dox b/doc/A05_PortingFrom2To3.dox
index 9c157b016..57f801f84 100644
--- a/doc/A05_PortingFrom2To3.dox
+++ b/doc/A05_PortingFrom2To3.dox
@@ -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.
*/