// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2014 Gael Guennebaud // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. #ifndef EIGEN_SPARSEPRODUCT_H #define EIGEN_SPARSEPRODUCT_H namespace Eigen { /** \returns an expression of the product of two sparse matrices. * By default a conservative product preserving the symbolic non zeros is performed. * The automatic pruning of the small values can be achieved by calling the pruned() function * in which case a totally different product algorithm is employed: * \code * C = (A*B).pruned(); // supress numerical zeros (exact) * C = (A*B).pruned(ref); * C = (A*B).pruned(ref,epsilon); * \endcode * where \c ref is a meaningful non zero reference value. * */ template template inline const Product SparseMatrixBase::operator*(const SparseMatrixBase &other) const { return Product(derived(), other.derived()); } namespace internal { // sparse * sparse template struct generic_product_impl { template static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) { typedef typename nested_eval::type LhsNested; typedef typename nested_eval::type RhsNested; LhsNested lhsNested(lhs); RhsNested rhsNested(rhs); internal::conservative_sparse_sparse_product_selector::type, typename remove_all::type, Dest>::run(lhsNested,rhsNested,dst); } }; // sparse * sparse-triangular template struct generic_product_impl : public generic_product_impl {}; // sparse-triangular * sparse template struct generic_product_impl : public generic_product_impl {}; // Dense = sparse * sparse template< typename DstXprType, typename Lhs, typename Rhs, int Options/*, typename Scalar*/> struct Assignment, internal::assign_op, Sparse2Dense/*, typename enable_if<(Options==DefaultProduct || Options==AliasFreeProduct),Scalar>::type*/> { typedef Product SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op &) { dst.setZero(); dst += src; } }; // Dense += sparse * sparse template< typename DstXprType, typename Lhs, typename Rhs, int Options> struct Assignment, internal::add_assign_op, Sparse2Dense/*, typename enable_if<(Options==DefaultProduct || Options==AliasFreeProduct),Scalar>::type*/> { typedef Product SrcXprType; static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op &) { typedef typename nested_eval::type LhsNested; typedef typename nested_eval::type RhsNested; LhsNested lhsNested(src.lhs()); RhsNested rhsNested(src.rhs()); internal::sparse_sparse_to_dense_product_selector::type, typename remove_all::type, DstXprType>::run(lhsNested,rhsNested,dst); } }; template struct evaluator > > : public evaluator::PlainObject> { typedef SparseView > XprType; typedef typename XprType::PlainObject PlainObject; typedef evaluator Base; explicit evaluator(const XprType& xpr) : m_result(xpr.rows(), xpr.cols()) { using std::abs; ::new (static_cast(this)) Base(m_result); typedef typename nested_eval::type LhsNested; typedef typename nested_eval::type RhsNested; LhsNested lhsNested(xpr.nestedExpression().lhs()); RhsNested rhsNested(xpr.nestedExpression().rhs()); internal::sparse_sparse_product_with_pruning_selector::type, typename remove_all::type, PlainObject>::run(lhsNested,rhsNested,m_result, abs(xpr.reference())*xpr.epsilon()); } protected: PlainObject m_result; }; } // end namespace internal } // end namespace Eigen #endif // EIGEN_SPARSEPRODUCT_H