diff --git a/Eigen/src/Sparse/SparseBlock.h b/Eigen/src/Sparse/SparseBlock.h index 7f2e05c4d..a8c1f9047 100644 --- a/Eigen/src/Sparse/SparseBlock.h +++ b/Eigen/src/Sparse/SparseBlock.h @@ -264,10 +264,18 @@ class SparseInnerVectorSet, Size> inline const Scalar* _valuePtr() const { return m_matrix._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; } + inline Scalar* _valuePtr() + { return m_matrix.const_cast_derived()._valuePtr() + m_matrix._outerIndexPtr()[m_outerStart]; } + inline const int* _innerIndexPtr() const { return m_matrix._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; } + inline int* _innerIndexPtr() + { return m_matrix.const_cast_derived()._innerIndexPtr() + m_matrix._outerIndexPtr()[m_outerStart]; } + inline const int* _outerIndexPtr() const { return m_matrix._outerIndexPtr() + m_outerStart; } + inline int* _outerIndexPtr() + { return m_matrix.const_cast_derived()._outerIndexPtr() + m_outerStart; } int nonZeros() const { diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index 7feb2aff8..aa094d703 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -201,6 +201,14 @@ class SparseMatrix return m_data.value(id); } + inline Scalar& insertBackNoCheck(int outer, int inner) + { + int id = m_outerIndex[outer+1]; + ++m_outerIndex[outer+1]; + m_data.append(0, inner); + return m_data.value(id); + } + inline void startVec(int outer) { ei_assert(m_outerIndex[outer]==int(m_data.size()) && "you must call startVec on each inner vec"); @@ -443,7 +451,7 @@ class SparseMatrix } template - inline SparseMatrix& operator=(const SparseMatrixBase& other) + EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase& other) { const bool needToTranspose = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit); if (needToTranspose) @@ -479,13 +487,14 @@ class SparseMatrix m_data.resize(count); // pass 2 for (int j=0; j class SparseMatrixBase : public AnyMatrixBase inline Derived& operator=(const SparseProduct& product); + template + inline void _experimentalNewProduct(const Lhs& lhs, const Rhs& rhs); + friend std::ostream & operator << (std::ostream & s, const SparseMatrixBase& m) { if (Flags&RowMajorBit) diff --git a/Eigen/src/Sparse/SparseProduct.h b/Eigen/src/Sparse/SparseProduct.h index 08f6e3cac..3a47df6aa 100644 --- a/Eigen/src/Sparse/SparseProduct.h +++ b/Eigen/src/Sparse/SparseProduct.h @@ -32,8 +32,8 @@ struct SparseProductReturnType enum { LhsRowMajor = ei_traits::Flags & RowMajorBit, RhsRowMajor = ei_traits::Flags & RowMajorBit, - TransposeRhs = (!LhsRowMajor) && RhsRowMajor, - TransposeLhs = LhsRowMajor && (!RhsRowMajor) + TransposeRhs = /*false,*/ (!LhsRowMajor) && RhsRowMajor, + TransposeLhs = /*false*/ LhsRowMajor && (!RhsRowMajor) }; // FIXME if we transpose let's evaluate to a LinkedVectorMatrix since it is the @@ -136,6 +136,84 @@ class SparseProduct : ei_no_assignment_operator, RhsNested m_rhs; }; +template +static void ei_sparse_product_impl2(const Lhs& lhs, const Rhs& rhs, ResultType& res) +{ + typedef typename ei_traits::type>::Scalar Scalar; + + // make sure to call innerSize/outerSize since we fake the storage order. + int rows = lhs.innerSize(); + int cols = rhs.outerSize(); + ei_assert(lhs.outerSize() == rhs.innerSize()); + + std::vector mask(rows,false); + + // 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); + + float ratio; + + res.resize(rows, cols); + res.reserve(int(ratioRes*rows*cols)); + // we compute each column of the result, one after the other + for (int j=0; j use a quick sort + // otherwise => loop through the entire vector + SparseInnerVectorSet vec(res,j); + + int nnz = vec.nonZeros(); + if(rows/1.39 > nnz * log2(nnz)) + { + std::sort(vec._innerIndexPtr(), vec._innerIndexPtr()+vec.nonZeros()); + for (typename ResultType::InnerIterator it(res, j); it; ++it) + { + it.valueRef() = values[it.index()]; + mask[it.index()] = false; + } + } + else + { + // dense path + int count = 0; + for(int i=0; i static void ei_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& res) @@ -257,6 +335,136 @@ inline Derived& SparseMatrixBase::operator=(const SparseProduct::Flags&RowMajorBit, + int RhsStorageOrder = ei_traits::Flags&RowMajorBit, + int ResStorageOrder = ei_traits::Flags&RowMajorBit> +struct ei_sparse_product_selector2; + +template +struct ei_sparse_product_selector2 +{ + typedef typename ei_traits::type>::Scalar Scalar; + + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + ei_sparse_product_impl2(lhs, rhs, res, 0); + } +}; + +template +struct ei_sparse_product_selector2 +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + RowMajorMatrix rhsRow = rhs; + RowMajorMatrix resRow(res.rows(), res.cols()); + ei_sparse_product_impl2(rhsRow, lhs, resRow); + res = resRow; + } +}; + +template +struct ei_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()); + ei_sparse_product_impl2(rhs, lhsRow, resRow); + res = resRow; + } +}; + +template +struct ei_sparse_product_selector2 +{ + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix RowMajorMatrix; + RowMajorMatrix resRow(res.rows(), res.cols()); + ei_sparse_product_impl2(rhs, lhs, resRow); + res = resRow; + } +}; + + +template +struct ei_sparse_product_selector2 +{ + typedef typename ei_traits::type>::Scalar Scalar; + + static void run(const Lhs& lhs, const Rhs& rhs, ResultType& res) + { + typedef SparseMatrix ColMajorMatrix; + ColMajorMatrix resCol(res.rows(), res.cols()); + ei_sparse_product_impl2(lhs, rhs, resCol); + res = resCol; + } +}; + +template +struct ei_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()); + ei_sparse_product_impl2(lhsCol, rhs, resCol); + res = resCol; + } +}; + +template +struct ei_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()); + ei_sparse_product_impl2(lhs, rhsCol, resCol); + res = resCol; + } +}; + +template +struct ei_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()); +// ei_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()); + ei_sparse_product_impl2(lhsCol, rhsCol, resCol); + res = resCol; + } +}; + +template +template +inline void SparseMatrixBase::_experimentalNewProduct(const Lhs& lhs, const Rhs& rhs) +{ + //derived().resize(lhs.rows(), rhs.cols()); + ei_sparse_product_selector2< + typename ei_cleantype::type, + typename ei_cleantype::type, + Derived>::run(lhs,rhs,derived()); +} + + + template struct ei_traits > : ei_traits, Lhs, Rhs> >