From 66e99ab6a1444d8e3d47211e4540837e6b982a3a Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Mon, 6 Jun 2016 15:11:41 +0200 Subject: Relax mixing-type constraints for binary coefficient-wise operators: - Replace internal::scalar_product_traits by Eigen::ScalarBinaryOpTraits - Remove the "functor_is_product_like" helper (was pretty ugly) - Currently, OP is not used, but it is available to the user for fine grained tuning - Currently, only the following operators have been generalized: *,/,+,-,=,*=,/=,+=,-= - TODO: generalize all other binray operators (comparisons,pow,etc.) - TODO: handle "scalar op array" operators (currently only * is handled) - TODO: move the handling of the "void" scalar type to ScalarBinaryOpTraits --- Eigen/src/SparseCore/SparseSelfAdjointView.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Eigen/src/SparseCore/SparseSelfAdjointView.h') diff --git a/Eigen/src/SparseCore/SparseSelfAdjointView.h b/Eigen/src/SparseCore/SparseSelfAdjointView.h index b92bb17e2..4f0c84d88 100644 --- a/Eigen/src/SparseCore/SparseSelfAdjointView.h +++ b/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -223,13 +223,13 @@ struct Assignment - static void run(SparseMatrix &dst, const SrcXprType &src, const internal::assign_op &/*func*/) + static void run(SparseMatrix &dst, const SrcXprType &src, const internal::assign_op &/*func*/) { internal::permute_symm_to_fullsymm(src.matrix(), dst); } template - static void run(DynamicSparseMatrix& dst, const SrcXprType &src, const internal::assign_op &/*func*/) + static void run(DynamicSparseMatrix& dst, const SrcXprType &src, const internal::assign_op &/*func*/) { // TODO directly evaluate into dst; SparseMatrix tmp(dst.rows(),dst.cols()); @@ -586,12 +586,12 @@ class SparseSymmetricPermutationProduct namespace internal { template -struct Assignment, internal::assign_op, Sparse2Sparse> +struct Assignment, internal::assign_op, Sparse2Sparse> { typedef SparseSymmetricPermutationProduct SrcXprType; typedef typename DstXprType::StorageIndex DstIndex; template - static void run(SparseMatrix &dst, const SrcXprType &src, const internal::assign_op &) + static void run(SparseMatrix &dst, const SrcXprType &src, const internal::assign_op &) { // internal::permute_symm_to_fullsymm(m_matrix,_dest,m_perm.indices().data()); SparseMatrix tmp; @@ -600,7 +600,7 @@ struct Assignment } template - static void run(SparseSelfAdjointView& dst, const SrcXprType &src, const internal::assign_op &) + static void run(SparseSelfAdjointView& dst, const SrcXprType &src, const internal::assign_op &) { internal::permute_symm_to_symm(src.matrix(),dst.matrix(),src.perm().indices().data()); } -- cgit v1.2.3 From 91b303901307b8bcebaea3211d26e13422121e78 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Mon, 4 Jul 2016 11:02:00 +0200 Subject: Change the semantic of the last template parameter of Assignment from "Scalar" to "SFINAE" only. The previous "Scalar" semantic was obsolete since we allow for different scalar types in the source and destination expressions. On can still specialize on scalar types through SFINAE and/or assignment functor. --- Eigen/src/Core/AssignEvaluator.h | 10 +++++----- Eigen/src/Core/DiagonalMatrix.h | 4 ++-- Eigen/src/Core/Solve.h | 6 +++--- Eigen/src/Core/TriangularMatrix.h | 18 +++++++++--------- Eigen/src/Geometry/Homogeneous.h | 4 ++-- Eigen/src/QR/ColPivHouseholderQR.h | 2 +- Eigen/src/QR/CompleteOrthogonalDecomposition.h | 2 +- Eigen/src/QR/FullPivHouseholderQR.h | 2 +- Eigen/src/SparseCore/SparseAssign.h | 15 ++++++++------- Eigen/src/SparseCore/SparseSelfAdjointView.h | 4 ++-- 10 files changed, 34 insertions(+), 33 deletions(-) (limited to 'Eigen/src/SparseCore/SparseSelfAdjointView.h') diff --git a/Eigen/src/Core/AssignEvaluator.h b/Eigen/src/Core/AssignEvaluator.h index 1df717bac..e9f2bc02d 100644 --- a/Eigen/src/Core/AssignEvaluator.h +++ b/Eigen/src/Core/AssignEvaluator.h @@ -709,7 +709,7 @@ template<> struct AssignmentKind { typedef Dense2Dense Ki // This is the main assignment class template< typename DstXprType, typename SrcXprType, typename Functor, typename Kind = typename AssignmentKind< typename evaluator_traits::Shape , typename evaluator_traits::Shape >::Kind, - typename Scalar = typename DstXprType::Scalar> + typename EnableIf = void> struct Assignment; @@ -816,8 +816,8 @@ void call_assignment_no_alias_no_transpose(Dst& dst, const Src& src) template void check_for_aliasing(const Dst &dst, const Src &src); // Generic Dense to Dense assignment -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const Functor &func) @@ -834,8 +834,8 @@ struct Assignment // Generic assignment through evalTo. // TODO: not sure we have to keep that one, but it helps porting current code to new evaluator mechanism. -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) diff --git a/Eigen/src/Core/DiagonalMatrix.h b/Eigen/src/Core/DiagonalMatrix.h index d6f89bced..92b2eee71 100644 --- a/Eigen/src/Core/DiagonalMatrix.h +++ b/Eigen/src/Core/DiagonalMatrix.h @@ -316,8 +316,8 @@ struct Diagonal2Dense {}; template<> struct AssignmentKind { typedef Diagonal2Dense Kind; }; // Diagonal matrix to Dense assignment -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) { diff --git a/Eigen/src/Core/Solve.h b/Eigen/src/Core/Solve.h index 038ad5b11..8fc69c4b8 100644 --- a/Eigen/src/Core/Solve.h +++ b/Eigen/src/Core/Solve.h @@ -134,7 +134,7 @@ protected: // Specialization for "dst = dec.solve(rhs)" // NOTE we need to specialize it for Dense2Dense to avoid ambiguous specialization error and a Sparse2Sparse specialization must exist somewhere template -struct Assignment, internal::assign_op, Dense2Dense, Scalar> +struct Assignment, internal::assign_op, Dense2Dense> { typedef Solve SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) @@ -146,7 +146,7 @@ struct Assignment, internal::assign_op -struct Assignment,RhsType>, internal::assign_op, Dense2Dense, Scalar> +struct Assignment,RhsType>, internal::assign_op, Dense2Dense> { typedef Solve,RhsType> SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) @@ -158,7 +158,7 @@ struct Assignment,RhsType>, internal: // Specialization for "dst = dec.adjoint().solve(rhs)" template struct Assignment, const Transpose >,RhsType>, - internal::assign_op, Dense2Dense, Scalar> + internal::assign_op, Dense2Dense> { typedef Solve, const Transpose >,RhsType> SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) diff --git a/Eigen/src/Core/TriangularMatrix.h b/Eigen/src/Core/TriangularMatrix.h index c599e0b32..e9606ec33 100644 --- a/Eigen/src/Core/TriangularMatrix.h +++ b/Eigen/src/Core/TriangularMatrix.h @@ -812,8 +812,8 @@ template<> struct AssignmentKind { typedef Tria template<> struct AssignmentKind { typedef Dense2Triangular Kind; }; -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) { @@ -823,8 +823,8 @@ struct Assignment -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) { @@ -832,8 +832,8 @@ struct Assignment } }; -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { EIGEN_DEVICE_FUNC static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) { @@ -933,7 +933,7 @@ namespace internal { // Triangular = Product template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> -struct Assignment, internal::assign_op::Scalar>, Dense2Triangular, Scalar> +struct Assignment, internal::assign_op::Scalar>, Dense2Triangular> { typedef Product SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) @@ -945,7 +945,7 @@ struct Assignment, internal::assign_ // Triangular += Product template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> -struct Assignment, internal::add_assign_op::Scalar>, Dense2Triangular, Scalar> +struct Assignment, internal::add_assign_op::Scalar>, Dense2Triangular> { typedef Product SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op &) @@ -956,7 +956,7 @@ struct Assignment, internal::add_ass // Triangular -= Product template< typename DstXprType, typename Lhs, typename Rhs, typename Scalar> -struct Assignment, internal::sub_assign_op::Scalar>, Dense2Triangular, Scalar> +struct Assignment, internal::sub_assign_op::Scalar>, Dense2Triangular> { typedef Product SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op &) diff --git a/Eigen/src/Geometry/Homogeneous.h b/Eigen/src/Geometry/Homogeneous.h index 1c35ca486..4e2213b33 100644 --- a/Eigen/src/Geometry/Homogeneous.h +++ b/Eigen/src/Geometry/Homogeneous.h @@ -329,7 +329,7 @@ protected: // dense = homogeneous template< typename DstXprType, typename ArgType, typename Scalar> -struct Assignment, internal::assign_op, Dense2Dense, Scalar> +struct Assignment, internal::assign_op, Dense2Dense> { typedef Homogeneous SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) @@ -341,7 +341,7 @@ struct Assignment, internal::assign_op // dense = homogeneous template< typename DstXprType, typename ArgType, typename Scalar> -struct Assignment, internal::assign_op, Dense2Dense, Scalar> +struct Assignment, internal::assign_op, Dense2Dense> { typedef Homogeneous SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) diff --git a/Eigen/src/QR/ColPivHouseholderQR.h b/Eigen/src/QR/ColPivHouseholderQR.h index 525ee8c18..e847bc434 100644 --- a/Eigen/src/QR/ColPivHouseholderQR.h +++ b/Eigen/src/QR/ColPivHouseholderQR.h @@ -598,7 +598,7 @@ void ColPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType & namespace internal { template -struct Assignment >, internal::assign_op, Dense2Dense, Scalar> +struct Assignment >, internal::assign_op, Dense2Dense> { typedef ColPivHouseholderQR QrType; typedef Inverse SrcXprType; diff --git a/Eigen/src/QR/CompleteOrthogonalDecomposition.h b/Eigen/src/QR/CompleteOrthogonalDecomposition.h index 52bcc2173..398e1aa77 100644 --- a/Eigen/src/QR/CompleteOrthogonalDecomposition.h +++ b/Eigen/src/QR/CompleteOrthogonalDecomposition.h @@ -510,7 +510,7 @@ void CompleteOrthogonalDecomposition<_MatrixType>::_solve_impl( namespace internal { template -struct Assignment >, internal::assign_op, Dense2Dense, Scalar> +struct Assignment >, internal::assign_op, Dense2Dense> { typedef CompleteOrthogonalDecomposition CodType; typedef Inverse SrcXprType; diff --git a/Eigen/src/QR/FullPivHouseholderQR.h b/Eigen/src/QR/FullPivHouseholderQR.h index 4f55d52a5..e21966056 100644 --- a/Eigen/src/QR/FullPivHouseholderQR.h +++ b/Eigen/src/QR/FullPivHouseholderQR.h @@ -560,7 +560,7 @@ void FullPivHouseholderQR<_MatrixType>::_solve_impl(const RhsType &rhs, DstType namespace internal { template -struct Assignment >, internal::assign_op, Dense2Dense, Scalar> +struct Assignment >, internal::assign_op, Dense2Dense> { typedef FullPivHouseholderQR QrType; typedef Inverse SrcXprType; diff --git a/Eigen/src/SparseCore/SparseAssign.h b/Eigen/src/SparseCore/SparseAssign.h index b284fa9e4..fa5386599 100644 --- a/Eigen/src/SparseCore/SparseAssign.h +++ b/Eigen/src/SparseCore/SparseAssign.h @@ -124,8 +124,8 @@ void assign_sparse_to_sparse(DstXprType &dst, const SrcXprType &src) } // Generic Sparse to Sparse assignment -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &/*func*/) { @@ -134,8 +134,8 @@ struct Assignment }; // Generic Sparse to Dense assignment -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { static void run(DstXprType &dst, const SrcXprType &src, const Functor &func) { @@ -156,7 +156,7 @@ struct Assignment // Specialization for "dst = dec.solve(rhs)" // NOTE we need to specialize it for Sparse2Sparse to avoid ambiguous specialization error template -struct Assignment, internal::assign_op, Sparse2Sparse, Scalar> +struct Assignment, internal::assign_op, Sparse2Sparse> { typedef Solve SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) @@ -169,10 +169,11 @@ struct Diagonal2Sparse {}; template<> struct AssignmentKind { typedef Diagonal2Sparse Kind; }; -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { typedef typename DstXprType::StorageIndex StorageIndex; + typedef typename DstXprType::Scalar Scalar; typedef Array ArrayXI; typedef Array ArrayXS; template diff --git a/Eigen/src/SparseCore/SparseSelfAdjointView.h b/Eigen/src/SparseCore/SparseSelfAdjointView.h index 4f0c84d88..a48520c0c 100644 --- a/Eigen/src/SparseCore/SparseSelfAdjointView.h +++ b/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -218,8 +218,8 @@ struct SparseSelfAdjoint2Sparse {}; template<> struct AssignmentKind { typedef SparseSelfAdjoint2Sparse Kind; }; template<> struct AssignmentKind { typedef Sparse2Sparse Kind; }; -template< typename DstXprType, typename SrcXprType, typename Functor, typename Scalar> -struct Assignment +template< typename DstXprType, typename SrcXprType, typename Functor> +struct Assignment { typedef typename DstXprType::StorageIndex StorageIndex; template -- cgit v1.2.3 From 441b7eaab2569e939928ec345a1368e33fd65d31 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 24 Aug 2016 13:06:34 +0200 Subject: Add support for non trivial scalar factor in sparse selfadjoint * dense products, and enable +=/-= assignement for such products. This changeset also improves the performance by working on column of the result at once. --- Eigen/src/SparseCore/SparseSelfAdjointView.h | 73 ++++++++++++++++------------ test/sparse_product.cpp | 4 ++ 2 files changed, 47 insertions(+), 30 deletions(-) (limited to 'Eigen/src/SparseCore/SparseSelfAdjointView.h') diff --git a/Eigen/src/SparseCore/SparseSelfAdjointView.h b/Eigen/src/SparseCore/SparseSelfAdjointView.h index a48520c0c..d31d9babf 100644 --- a/Eigen/src/SparseCore/SparseSelfAdjointView.h +++ b/Eigen/src/SparseCore/SparseSelfAdjointView.h @@ -250,11 +250,11 @@ template LhsEval; - typedef typename evaluator::InnerIterator LhsIterator; + typedef typename internal::nested_eval::type SparseLhsTypeNested; + typedef typename internal::remove_all::type SparseLhsTypeNestedCleaned; + typedef evaluator LhsEval; + typedef typename LhsEval::InnerIterator LhsIterator; typedef typename SparseLhsType::Scalar LhsScalar; enum { @@ -266,39 +266,53 @@ inline void sparse_selfadjoint_time_dense_product(const SparseLhsType& lhs, cons ProcessSecondHalf = !ProcessFirstHalf }; - LhsEval lhsEval(lhs); - - for (Index j=0; j::ReturnType rhs_j(alpha*rhs(j,k)); + // accumulator for partial scalar product + typename DenseResType::Scalar res_j(0); + for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i) + { + LhsScalar lhs_ij = i.value(); + if(!LhsIsRowMajor) lhs_ij = numext::conj(lhs_ij); + res_j += lhs_ij * rhs(i.index(),k); + res(i.index(),k) += numext::conj(lhs_ij) * rhs_j; + } + res(j,k) += alpha * res_j; + + // handle diagonal coeff + if (ProcessFirstHalf && i && (i.index()==j)) + res(j,k) += alpha * i.value() * rhs(j,k); } - for(; (ProcessFirstHalf ? i && i.index() < j : i) ; ++i) - { - Index a = LhsIsRowMajor ? j : i.index(); - Index b = LhsIsRowMajor ? i.index() : j; - LhsScalar v = i.value(); - res.row(a) += (v) * rhs.row(b); - res.row(b) += numext::conj(v) * rhs.row(a); - } - if (ProcessFirstHalf && i && (i.index()==j)) - res.row(j) += i.value() * rhs.row(j); } } template struct generic_product_impl +: generic_product_impl_base > { template - static void evalTo(Dest& dst, const LhsView& lhsView, const Rhs& rhs) + static void scaleAndAddTo(Dest& dst, const LhsView& lhsView, const Rhs& rhs, const typename Dest::Scalar& alpha) { typedef typename LhsView::_MatrixTypeNested Lhs; typedef typename nested_eval::type LhsNested; @@ -306,16 +320,16 @@ struct generic_product_impl(lhsNested, rhsNested, dst, typename Dest::Scalar(1)); + internal::sparse_selfadjoint_time_dense_product(lhsNested, rhsNested, dst, alpha); } }; template struct generic_product_impl +: generic_product_impl_base > { template - static void evalTo(Dest& dst, const Lhs& lhs, const RhsView& rhsView) + static void scaleAndAddTo(Dest& dst, const Lhs& lhs, const RhsView& rhsView, const typename Dest::Scalar& alpha) { typedef typename RhsView::_MatrixTypeNested Rhs; typedef typename nested_eval::type LhsNested; @@ -323,10 +337,9 @@ struct generic_product_impl dstT(dst); - internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, typename Dest::Scalar(1)); + internal::sparse_selfadjoint_time_dense_product(rhsNested.transpose(), lhsNested.transpose(), dstT, alpha); } }; diff --git a/test/sparse_product.cpp b/test/sparse_product.cpp index c518a6e55..c7c93373d 100644 --- a/test/sparse_product.cpp +++ b/test/sparse_product.cpp @@ -292,6 +292,10 @@ template void sparse_product() VERIFY_IS_APPROX(x=mUp.template selfadjointView()*b, refX=refS*b); VERIFY_IS_APPROX(x=mLo.template selfadjointView()*b, refX=refS*b); VERIFY_IS_APPROX(x=mS.template selfadjointView()*b, refX=refS*b); + + VERIFY_IS_APPROX(x.noalias()+=mUp.template selfadjointView()*b, refX+=refS*b); + VERIFY_IS_APPROX(x.noalias()-=mLo.template selfadjointView()*b, refX-=refS*b); + VERIFY_IS_APPROX(x.noalias()+=mS.template selfadjointView()*b, refX+=refS*b); // sparse selfadjointView with sparse matrices SparseMatrixType mSres(rows,rows); -- cgit v1.2.3