// This file is part of Eigen, a lightweight C++ template library // for linear algebra. // // Copyright (C) 2008-2010 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 3 of the License, or (at your option) any later version. // // Alternatively, you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 2 of // the License, or (at your option) any later version. // // Eigen is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License and a copy of the GNU General Public License along with // Eigen. If not, see . #ifndef EIGEN_SPARSESPARSEPRODUCT_H #define EIGEN_SPARSESPARSEPRODUCT_H namespace internal { template static void sparse_product_impl2(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef typename remove_all::type::Scalar Scalar; typedef typename remove_all::type::Index Index; // make sure to call innerSize/outerSize since we fake the storage order. Index rows = lhs.innerSize(); Index cols = rhs.outerSize(); eigen_assert(lhs.outerSize() == rhs.innerSize()); std::vector mask(rows,false); Matrix values(rows); Matrix indices(rows); // estimate the number of non zero entries float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols())); float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols); float ratioRes = std::min(ratioLhs * avgNnzPerRhsColumn, 1.f); // int t200 = rows/(log2(200)*1.39); // int t = (rows*100)/139; res.resize(rows, cols); res.reserve(Index(ratioRes*rows*cols)); // we compute each column of the result, one after the other for (Index j=0; j use a quick sort // otherwise => loop through the entire vector // In order to avoid to perform an expensive log2 when the // result is clearly very sparse we use a linear bound up to 200. // if((nnz<200 && nnz1) std::sort(indices.data(),indices.data()+nnz); // for(int k=0; k static void sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) { // return sparse_product_impl2(lhs,rhs,res); typedef typename remove_all::type::Scalar Scalar; typedef typename remove_all::type::Index Index; // make sure to call innerSize/outerSize since we fake the storage order. Index rows = lhs.innerSize(); Index cols = rhs.outerSize(); //int size = lhs.outerSize(); eigen_assert(lhs.outerSize() == rhs.innerSize()); // allocate a temporary buffer AmbiVector tempVector(rows); // estimate the number of non zero entries float ratioLhs = float(lhs.nonZeros())/(float(lhs.rows())*float(lhs.cols())); float avgNnzPerRhsColumn = float(rhs.nonZeros())/float(cols); float ratioRes = std::min(ratioLhs * avgNnzPerRhsColumn, 1.f); res.resize(rows, cols); res.reserve(Index(ratioRes*rows*cols)); for (Index j=0; j::Iterator it(tempVector); it; ++it) res.insertBackByOuterInner(j,it.index()) = it.value(); } res.finalize(); } template::Flags&RowMajorBit, int RhsStorageOrder = traits::Flags&RowMajorBit, int ResStorageOrder = traits::Flags&RowMajorBit> struct sparse_product_selector; template struct sparse_product_selector { typedef typename traits::type>::Scalar Scalar; static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { // std::cerr << __LINE__ << "\n"; typename remove_all::type _res(res.rows(), res.cols()); sparse_product_impl(lhs, rhs, _res); res.swap(_res); } }; template struct sparse_product_selector { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { // std::cerr << __LINE__ << "\n"; // we need a col-major matrix to hold the result typedef SparseMatrix SparseTemporaryType; SparseTemporaryType _res(res.rows(), res.cols()); sparse_product_impl(lhs, rhs, _res); res = _res; } }; template struct sparse_product_selector { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { // std::cerr << __LINE__ << "\n"; // let's transpose the product to get a column x column product typename remove_all::type _res(res.rows(), res.cols()); sparse_product_impl(rhs, lhs, _res); res.swap(_res); } }; template struct sparse_product_selector { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { // std::cerr << "here...\n"; typedef SparseMatrix ColMajorMatrix; ColMajorMatrix colLhs(lhs); ColMajorMatrix colRhs(rhs); // std::cerr << "more...\n"; sparse_product_impl(colLhs, colRhs, res); // std::cerr << "OK.\n"; // let's transpose the product to get a column x column product // typedef SparseMatrix SparseTemporaryType; // SparseTemporaryType _res(res.cols(), res.rows()); // sparse_product_impl(rhs, lhs, _res); // res = _res.transpose(); } }; // NOTE the 2 others cases (col row *) must never occur since they are caught // by ProductReturnType which transforms it to (col col *) by evaluating rhs. } // end namespace internal // sparse = sparse * sparse template template inline Derived& SparseMatrixBase::operator=(const SparseSparseProduct& product) { // std::cerr << "there..." << typeid(Lhs).name() << " " << typeid(Lhs).name() << " " << (Derived::Flags&&RowMajorBit) << "\n"; internal::sparse_product_selector< typename internal::remove_all::type, typename internal::remove_all::type, Derived>::run(product.lhs(),product.rhs(),derived()); return derived(); } namespace internal { template::Flags&RowMajorBit, int RhsStorageOrder = traits::Flags&RowMajorBit, int ResStorageOrder = traits::Flags&RowMajorBit> struct sparse_product_selector2; template struct sparse_product_selector2 { typedef typename traits::type>::Scalar Scalar; static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { sparse_product_impl2(lhs, rhs, res); } }; template struct sparse_product_selector2 { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { // prevent warnings until the code is fixed EIGEN_UNUSED_VARIABLE(lhs); EIGEN_UNUSED_VARIABLE(rhs); EIGEN_UNUSED_VARIABLE(res); // typedef SparseMatrix RowMajorMatrix; // RowMajorMatrix rhsRow = rhs; // RowMajorMatrix resRow(res.rows(), res.cols()); // sparse_product_impl2(rhsRow, lhs, resRow); // res = resRow; } }; template struct sparse_product_selector2 { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef SparseMatrix RowMajorMatrix; RowMajorMatrix lhsRow = lhs; RowMajorMatrix resRow(res.rows(), res.cols()); sparse_product_impl2(rhs, lhsRow, resRow); res = resRow; } }; template struct sparse_product_selector2 { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef SparseMatrix RowMajorMatrix; RowMajorMatrix resRow(res.rows(), res.cols()); sparse_product_impl2(rhs, lhs, resRow); res = resRow; } }; template struct sparse_product_selector2 { typedef typename traits::type>::Scalar Scalar; static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef SparseMatrix ColMajorMatrix; ColMajorMatrix resCol(res.rows(), res.cols()); sparse_product_impl2(lhs, rhs, resCol); res = resCol; } }; template struct sparse_product_selector2 { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef SparseMatrix ColMajorMatrix; ColMajorMatrix lhsCol = lhs; ColMajorMatrix resCol(res.rows(), res.cols()); sparse_product_impl2(lhsCol, rhs, resCol); res = resCol; } }; template struct sparse_product_selector2 { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef SparseMatrix ColMajorMatrix; ColMajorMatrix rhsCol = rhs; ColMajorMatrix resCol(res.rows(), res.cols()); sparse_product_impl2(lhs, rhsCol, resCol); res = resCol; } }; template struct sparse_product_selector2 { static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) { typedef SparseMatrix ColMajorMatrix; // ColMajorMatrix lhsTr(lhs); // ColMajorMatrix rhsTr(rhs); // ColMajorMatrix aux(res.rows(), res.cols()); // sparse_product_impl2(rhs, lhs, aux); // // ColMajorMatrix aux2 = aux.transpose(); // res = aux; typedef SparseMatrix ColMajorMatrix; ColMajorMatrix lhsCol(lhs); ColMajorMatrix rhsCol(rhs); ColMajorMatrix resCol(res.rows(), res.cols()); sparse_product_impl2(lhsCol, rhsCol, resCol); res = resCol; } }; } // end namespace internal template template inline void SparseMatrixBase::_experimentalNewProduct(const Lhs& lhs, const Rhs& rhs) { //derived().resize(lhs.rows(), rhs.cols()); internal::sparse_product_selector2< typename internal::remove_all::type, typename internal::remove_all::type, Derived>::run(lhs,rhs,derived()); } // sparse * sparse template template inline const typename SparseSparseProductReturnType::Type SparseMatrixBase::operator*(const SparseMatrixBase &other) const { return typename SparseSparseProductReturnType::Type(derived(), other.derived()); } #endif // EIGEN_SPARSESPARSEPRODUCT_H