diff options
Diffstat (limited to 'Eigen/src/SparseCore/SparseProduct.h')
-rw-r--r-- | Eigen/src/SparseCore/SparseProduct.h | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/Eigen/src/SparseCore/SparseProduct.h b/Eigen/src/SparseCore/SparseProduct.h new file mode 100644 index 0000000..af8a774 --- /dev/null +++ b/Eigen/src/SparseCore/SparseProduct.h @@ -0,0 +1,181 @@ +// This file is part of Eigen, a lightweight C++ template library +// for linear algebra. +// +// Copyright (C) 2008-2015 Gael Guennebaud <gael.guennebaud@inria.fr> +// +// 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(); // suppress 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<typename Derived> +template<typename OtherDerived> +inline const Product<Derived,OtherDerived,AliasFreeProduct> +SparseMatrixBase<Derived>::operator*(const SparseMatrixBase<OtherDerived> &other) const +{ + return Product<Derived,OtherDerived,AliasFreeProduct>(derived(), other.derived()); +} + +namespace internal { + +// sparse * sparse +template<typename Lhs, typename Rhs, int ProductType> +struct generic_product_impl<Lhs, Rhs, SparseShape, SparseShape, ProductType> +{ + template<typename Dest> + static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs) + { + evalTo(dst, lhs, rhs, typename evaluator_traits<Dest>::Shape()); + } + + // dense += sparse * sparse + template<typename Dest,typename ActualLhs> + static void addTo(Dest& dst, const ActualLhs& lhs, const Rhs& rhs, typename enable_if<is_same<typename evaluator_traits<Dest>::Shape,DenseShape>::value,int*>::type* = 0) + { + typedef typename nested_eval<ActualLhs,Dynamic>::type LhsNested; + typedef typename nested_eval<Rhs,Dynamic>::type RhsNested; + LhsNested lhsNested(lhs); + RhsNested rhsNested(rhs); + internal::sparse_sparse_to_dense_product_selector<typename remove_all<LhsNested>::type, + typename remove_all<RhsNested>::type, Dest>::run(lhsNested,rhsNested,dst); + } + + // dense -= sparse * sparse + template<typename Dest> + static void subTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, typename enable_if<is_same<typename evaluator_traits<Dest>::Shape,DenseShape>::value,int*>::type* = 0) + { + addTo(dst, -lhs, rhs); + } + +protected: + + // sparse = sparse * sparse + template<typename Dest> + static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, SparseShape) + { + typedef typename nested_eval<Lhs,Dynamic>::type LhsNested; + typedef typename nested_eval<Rhs,Dynamic>::type RhsNested; + LhsNested lhsNested(lhs); + RhsNested rhsNested(rhs); + internal::conservative_sparse_sparse_product_selector<typename remove_all<LhsNested>::type, + typename remove_all<RhsNested>::type, Dest>::run(lhsNested,rhsNested,dst); + } + + // dense = sparse * sparse + template<typename Dest> + static void evalTo(Dest& dst, const Lhs& lhs, const Rhs& rhs, DenseShape) + { + dst.setZero(); + addTo(dst, lhs, rhs); + } +}; + +// sparse * sparse-triangular +template<typename Lhs, typename Rhs, int ProductType> +struct generic_product_impl<Lhs, Rhs, SparseShape, SparseTriangularShape, ProductType> + : public generic_product_impl<Lhs, Rhs, SparseShape, SparseShape, ProductType> +{}; + +// sparse-triangular * sparse +template<typename Lhs, typename Rhs, int ProductType> +struct generic_product_impl<Lhs, Rhs, SparseTriangularShape, SparseShape, ProductType> + : public generic_product_impl<Lhs, Rhs, SparseShape, SparseShape, ProductType> +{}; + +// dense = sparse-product (can be sparse*sparse, sparse*perm, etc.) +template< typename DstXprType, typename Lhs, typename Rhs> +struct Assignment<DstXprType, Product<Lhs,Rhs,AliasFreeProduct>, internal::assign_op<typename DstXprType::Scalar,typename Product<Lhs,Rhs,AliasFreeProduct>::Scalar>, Sparse2Dense> +{ + typedef Product<Lhs,Rhs,AliasFreeProduct> SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &) + { + Index dstRows = src.rows(); + Index dstCols = src.cols(); + if((dst.rows()!=dstRows) || (dst.cols()!=dstCols)) + dst.resize(dstRows, dstCols); + + generic_product_impl<Lhs, Rhs>::evalTo(dst,src.lhs(),src.rhs()); + } +}; + +// dense += sparse-product (can be sparse*sparse, sparse*perm, etc.) +template< typename DstXprType, typename Lhs, typename Rhs> +struct Assignment<DstXprType, Product<Lhs,Rhs,AliasFreeProduct>, internal::add_assign_op<typename DstXprType::Scalar,typename Product<Lhs,Rhs,AliasFreeProduct>::Scalar>, Sparse2Dense> +{ + typedef Product<Lhs,Rhs,AliasFreeProduct> SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::add_assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &) + { + generic_product_impl<Lhs, Rhs>::addTo(dst,src.lhs(),src.rhs()); + } +}; + +// dense -= sparse-product (can be sparse*sparse, sparse*perm, etc.) +template< typename DstXprType, typename Lhs, typename Rhs> +struct Assignment<DstXprType, Product<Lhs,Rhs,AliasFreeProduct>, internal::sub_assign_op<typename DstXprType::Scalar,typename Product<Lhs,Rhs,AliasFreeProduct>::Scalar>, Sparse2Dense> +{ + typedef Product<Lhs,Rhs,AliasFreeProduct> SrcXprType; + static void run(DstXprType &dst, const SrcXprType &src, const internal::sub_assign_op<typename DstXprType::Scalar,typename SrcXprType::Scalar> &) + { + generic_product_impl<Lhs, Rhs>::subTo(dst,src.lhs(),src.rhs()); + } +}; + +template<typename Lhs, typename Rhs, int Options> +struct unary_evaluator<SparseView<Product<Lhs, Rhs, Options> >, IteratorBased> + : public evaluator<typename Product<Lhs, Rhs, DefaultProduct>::PlainObject> +{ + typedef SparseView<Product<Lhs, Rhs, Options> > XprType; + typedef typename XprType::PlainObject PlainObject; + typedef evaluator<PlainObject> Base; + + explicit unary_evaluator(const XprType& xpr) + : m_result(xpr.rows(), xpr.cols()) + { + using std::abs; + ::new (static_cast<Base*>(this)) Base(m_result); + typedef typename nested_eval<Lhs,Dynamic>::type LhsNested; + typedef typename nested_eval<Rhs,Dynamic>::type RhsNested; + LhsNested lhsNested(xpr.nestedExpression().lhs()); + RhsNested rhsNested(xpr.nestedExpression().rhs()); + + internal::sparse_sparse_product_with_pruning_selector<typename remove_all<LhsNested>::type, + typename remove_all<RhsNested>::type, PlainObject>::run(lhsNested,rhsNested,m_result, + abs(xpr.reference())*xpr.epsilon()); + } + +protected: + PlainObject m_result; +}; + +} // end namespace internal + +// sparse matrix = sparse-product (can be sparse*sparse, sparse*perm, etc.) +template<typename Scalar, int _Options, typename _StorageIndex> +template<typename Lhs, typename Rhs> +SparseMatrix<Scalar,_Options,_StorageIndex>& SparseMatrix<Scalar,_Options,_StorageIndex>::operator=(const Product<Lhs,Rhs,AliasFreeProduct>& src) +{ + // std::cout << "in Assignment : " << DstOptions << "\n"; + SparseMatrix dst(src.rows(),src.cols()); + internal::generic_product_impl<Lhs, Rhs>::evalTo(dst,src.lhs(),src.rhs()); + this->swap(dst); + return *this; +} + +} // end namespace Eigen + +#endif // EIGEN_SPARSEPRODUCT_H |