diff --git a/Eigen/src/Core/CwiseBinaryOp.h b/Eigen/src/Core/CwiseBinaryOp.h index aa3297354..9ddbfe286 100644 --- a/Eigen/src/Core/CwiseBinaryOp.h +++ b/Eigen/src/Core/CwiseBinaryOp.h @@ -84,6 +84,7 @@ class CwiseBinaryOp : { public: + typedef typename internal::remove_all::type Functor; typedef typename internal::remove_all::type Lhs; typedef typename internal::remove_all::type Rhs; diff --git a/Eigen/src/Core/util/Macros.h b/Eigen/src/Core/util/Macros.h index 89b796040..d577fd70d 100644 --- a/Eigen/src/Core/util/Macros.h +++ b/Eigen/src/Core/util/Macros.h @@ -12,8 +12,8 @@ #define EIGEN_MACROS_H #define EIGEN_WORLD_VERSION 3 -#define EIGEN_MAJOR_VERSION 2 -#define EIGEN_MINOR_VERSION 95 +#define EIGEN_MAJOR_VERSION 3 +#define EIGEN_MINOR_VERSION 0 #define EIGEN_VERSION_AT_LEAST(x,y,z) (EIGEN_WORLD_VERSION>x || (EIGEN_WORLD_VERSION>=x && \ (EIGEN_MAJOR_VERSION>y || (EIGEN_MAJOR_VERSION>=y && \ diff --git a/Eigen/src/SVD/JacobiSVD.h b/Eigen/src/SVD/JacobiSVD.h index ea2bd62eb..e0cfb6283 100644 --- a/Eigen/src/SVD/JacobiSVD.h +++ b/Eigen/src/SVD/JacobiSVD.h @@ -412,7 +412,7 @@ struct svd_precondition_2x2_block_to_be_real } // update largest diagonal entry - maxDiagEntry = numext::maxi(maxDiagEntry,numext::maxi(abs(work_matrix.coeff(p,p)), abs(work_matrix.coeff(q,q)))); + maxDiagEntry = numext::maxi(maxDiagEntry,numext::maxi(abs(work_matrix.coeff(p,p)), abs(work_matrix.coeff(q,q)))); // and check whether the 2x2 block is already diagonal RealScalar threshold = numext::maxi(considerAsZero, precision * maxDiagEntry); return abs(work_matrix.coeff(p,q))>threshold || abs(work_matrix.coeff(q,p)) > threshold; @@ -725,7 +725,7 @@ JacobiSVD::compute(const MatrixType& matrix, unsig if(computeV()) m_matrixV.applyOnTheRight(p,q,j_right); // keep track of the largest diagonal coefficient - maxDiagEntry = numext::maxi(maxDiagEntry,numext::maxi(abs(m_workMatrix.coeff(p,p)), abs(m_workMatrix.coeff(q,q)))); + maxDiagEntry = numext::maxi(maxDiagEntry,numext::maxi(abs(m_workMatrix.coeff(p,p)), abs(m_workMatrix.coeff(q,q)))); } } } diff --git a/Eigen/src/SparseCore/SparseCompressedBase.h b/Eigen/src/SparseCore/SparseCompressedBase.h index 55ad91f46..febd9039e 100644 --- a/Eigen/src/SparseCore/SparseCompressedBase.h +++ b/Eigen/src/SparseCore/SparseCompressedBase.h @@ -224,11 +224,11 @@ class SparseCompressedBase::ReverseInnerIterator } else { - m_start.value() = mat.outerIndexPtr()[outer]; + m_start = mat.outerIndexPtr()[outer]; if(mat.isCompressed()) m_id = mat.outerIndexPtr()[outer+1]; else - m_id = m_start.value() + mat.innerNonZeroPtr()[outer]; + m_id = m_start + mat.innerNonZeroPtr()[outer]; } } @@ -254,14 +254,15 @@ class SparseCompressedBase::ReverseInnerIterator inline Index row() const { return IsRowMajor ? m_outer.value() : index(); } inline Index col() const { return IsRowMajor ? index() : m_outer.value(); } - inline operator bool() const { return (m_id > m_start.value()); } + inline operator bool() const { return (m_id > m_start); } protected: const Scalar* m_values; const StorageIndex* m_indices; - const internal::variable_if_dynamic m_outer; + typedef internal::variable_if_dynamic OuterType; + const OuterType m_outer; Index m_id; - const internal::variable_if_dynamic m_start; + Index m_start; }; namespace internal { diff --git a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h index aad7b7d79..04cef66fc 100644 --- a/Eigen/src/SparseCore/SparseCwiseBinaryOp.h +++ b/Eigen/src/SparseCore/SparseCwiseBinaryOp.h @@ -325,16 +325,79 @@ protected: const XprType &m_expr; }; +template::Kind, + typename RhsKind = typename evaluator_traits::Kind, + typename LhsScalar = typename traits::Scalar, + typename RhsScalar = typename traits::Scalar> struct sparse_conjunction_evaluator; + // "sparse .* sparse" template struct binary_evaluator, Lhs, Rhs>, IteratorBased, IteratorBased> - : evaluator_base, Lhs, Rhs> > + : sparse_conjunction_evaluator, Lhs, Rhs> > +{ + typedef CwiseBinaryOp, Lhs, Rhs> XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; +// "dense .* sparse" +template +struct binary_evaluator, Lhs, Rhs>, IndexBased, IteratorBased> + : sparse_conjunction_evaluator, Lhs, Rhs> > +{ + typedef CwiseBinaryOp, Lhs, Rhs> XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; +// "sparse .* dense" +template +struct binary_evaluator, Lhs, Rhs>, IteratorBased, IndexBased> + : sparse_conjunction_evaluator, Lhs, Rhs> > +{ + typedef CwiseBinaryOp, Lhs, Rhs> XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; + +// "sparse && sparse" +template +struct binary_evaluator, IteratorBased, IteratorBased> + : sparse_conjunction_evaluator > +{ + typedef CwiseBinaryOp XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; +// "dense && sparse" +template +struct binary_evaluator, IndexBased, IteratorBased> + : sparse_conjunction_evaluator > +{ + typedef CwiseBinaryOp XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; +// "sparse && dense" +template +struct binary_evaluator, IteratorBased, IndexBased> + : sparse_conjunction_evaluator > +{ + typedef CwiseBinaryOp XprType; + typedef sparse_conjunction_evaluator Base; + explicit binary_evaluator(const XprType& xpr) : Base(xpr) {} +}; + +// "sparse ^ sparse" +template +struct sparse_conjunction_evaluator + : evaluator_base { protected: - typedef scalar_product_op BinaryOp; + typedef typename XprType::Functor BinaryOp; + typedef typename XprType::Lhs Lhs; + typedef typename XprType::Rhs Rhs; typedef typename evaluator::InnerIterator LhsIterator; typedef typename evaluator::InnerIterator RhsIterator; - typedef CwiseBinaryOp XprType; typedef typename XprType::StorageIndex StorageIndex; typedef typename traits::Scalar Scalar; public: @@ -344,7 +407,7 @@ public: { public: - EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer) + EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer) : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor) { while (m_lhsIter && m_rhsIter && (m_lhsIter.index() != m_rhsIter.index())) @@ -390,7 +453,7 @@ public: Flags = XprType::Flags }; - explicit binary_evaluator(const XprType& xpr) + explicit sparse_conjunction_evaluator(const XprType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) @@ -409,16 +472,17 @@ protected: evaluator m_rhsImpl; }; -// "dense .* sparse" -template -struct binary_evaluator, Lhs, Rhs>, IndexBased, IteratorBased> - : evaluator_base, Lhs, Rhs> > +// "dense ^ sparse" +template +struct sparse_conjunction_evaluator + : evaluator_base { protected: - typedef scalar_product_op BinaryOp; + typedef typename XprType::Functor BinaryOp; + typedef typename XprType::Lhs Lhs; + typedef typename XprType::Rhs Rhs; typedef evaluator LhsEvaluator; typedef typename evaluator::InnerIterator RhsIterator; - typedef CwiseBinaryOp XprType; typedef typename XprType::StorageIndex StorageIndex; typedef typename traits::Scalar Scalar; public: @@ -430,7 +494,7 @@ public: public: - EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer) + EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer) : m_lhsEval(aEval.m_lhsImpl), m_rhsIter(aEval.m_rhsImpl,outer), m_functor(aEval.m_functor), m_outer(outer) {} @@ -463,7 +527,7 @@ public: Flags = (XprType::Flags & ~RowMajorBit) | (int(Rhs::Flags)&RowMajorBit) }; - explicit binary_evaluator(const XprType& xpr) + explicit sparse_conjunction_evaluator(const XprType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) @@ -482,16 +546,17 @@ protected: evaluator m_rhsImpl; }; -// "sparse .* dense" -template -struct binary_evaluator, Lhs, Rhs>, IteratorBased, IndexBased> - : evaluator_base, Lhs, Rhs> > +// "sparse ^ dense" +template +struct sparse_conjunction_evaluator + : evaluator_base { protected: - typedef scalar_product_op BinaryOp; + typedef typename XprType::Functor BinaryOp; + typedef typename XprType::Lhs Lhs; + typedef typename XprType::Rhs Rhs; typedef typename evaluator::InnerIterator LhsIterator; typedef evaluator RhsEvaluator; - typedef CwiseBinaryOp XprType; typedef typename XprType::StorageIndex StorageIndex; typedef typename traits::Scalar Scalar; public: @@ -503,7 +568,7 @@ public: public: - EIGEN_STRONG_INLINE InnerIterator(const binary_evaluator& aEval, Index outer) + EIGEN_STRONG_INLINE InnerIterator(const sparse_conjunction_evaluator& aEval, Index outer) : m_lhsIter(aEval.m_lhsImpl,outer), m_rhsEval(aEval.m_rhsImpl), m_functor(aEval.m_functor), m_outer(outer) {} @@ -537,7 +602,7 @@ public: Flags = (XprType::Flags & ~RowMajorBit) | (int(Lhs::Flags)&RowMajorBit) }; - explicit binary_evaluator(const XprType& xpr) + explicit sparse_conjunction_evaluator(const XprType& xpr) : m_functor(xpr.functor()), m_lhsImpl(xpr.lhs()), m_rhsImpl(xpr.rhs()) diff --git a/Eigen/src/SparseCore/SparseMatrixBase.h b/Eigen/src/SparseCore/SparseMatrixBase.h index 8816bcff4..813accce1 100644 --- a/Eigen/src/SparseCore/SparseMatrixBase.h +++ b/Eigen/src/SparseCore/SparseMatrixBase.h @@ -214,10 +214,11 @@ template class SparseMatrixBase if (Flags&RowMajorBit) { const Nested nm(m.derived()); + internal::evaluator thisEval(nm); for (Index row=0; row::InnerIterator it(thisEval, row); it; ++it) { for ( ; col class SparseMatrixBase else { const Nested nm(m.derived()); + internal::evaluator thisEval(nm); if (m.cols() == 1) { Index row = 0; - for (typename NestedCleaned::InnerIterator it(nm.derived(), 0); it; ++it) + for (typename internal::evaluator::InnerIterator it(thisEval, 0); it; ++it) { for ( ; row,Constant,Derived operator/(const T& s,const StorageBaseType& a); #endif -/** \returns an expression of the coefficient-wise && operator of *this and \a other - * - * \warning this operator is for expression of bool only. - * - * Example: \include Cwise_boolean_and.cpp - * Output: \verbinclude Cwise_boolean_and.out - * - * \sa operator||(), select() - */ -template -EIGEN_DEVICE_FUNC -inline const CwiseBinaryOp -operator&&(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const -{ - EIGEN_STATIC_ASSERT((internal::is_same::value && internal::is_same::value), - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL); - return CwiseBinaryOp(derived(),other.derived()); -} - -/** \returns an expression of the coefficient-wise || operator of *this and \a other - * - * \warning this operator is for expression of bool only. - * - * Example: \include Cwise_boolean_or.cpp - * Output: \verbinclude Cwise_boolean_or.out - * - * \sa operator&&(), select() - */ -template -EIGEN_DEVICE_FUNC -inline const CwiseBinaryOp -operator||(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const -{ - EIGEN_STATIC_ASSERT((internal::is_same::value && internal::is_same::value), - THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL); - return CwiseBinaryOp(derived(),other.derived()); -} - /** \returns an expression of the coefficient-wise ^ operator of *this and \a other * * \warning this operator is for expression of bool only. diff --git a/Eigen/src/plugins/CommonCwiseBinaryOps.h b/Eigen/src/plugins/CommonCwiseBinaryOps.h index b51ee9e4c..8b6730ede 100644 --- a/Eigen/src/plugins/CommonCwiseBinaryOps.h +++ b/Eigen/src/plugins/CommonCwiseBinaryOps.h @@ -75,3 +75,41 @@ EIGEN_MAKE_SCALAR_BINARY_OP_ONTHERIGHT(operator/,quotient) template const CwiseBinaryOp,Derived,Constant > operator/(const T& scalar) const; #endif + +/** \returns an expression of the coefficient-wise boolean \b and operator of \c *this and \a other + * + * \warning this operator is for expression of bool only. + * + * Example: \include Cwise_boolean_and.cpp + * Output: \verbinclude Cwise_boolean_and.out + * + * \sa operator||(), select() + */ +template +EIGEN_DEVICE_FUNC +inline const CwiseBinaryOp +operator&&(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const +{ + EIGEN_STATIC_ASSERT((internal::is_same::value && internal::is_same::value), + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL); + return CwiseBinaryOp(derived(),other.derived()); +} + +/** \returns an expression of the coefficient-wise boolean \b or operator of \c *this and \a other + * + * \warning this operator is for expression of bool only. + * + * Example: \include Cwise_boolean_or.cpp + * Output: \verbinclude Cwise_boolean_or.out + * + * \sa operator&&(), select() + */ +template +EIGEN_DEVICE_FUNC +inline const CwiseBinaryOp +operator||(const EIGEN_CURRENT_STORAGE_BASE_CLASS &other) const +{ + EIGEN_STATIC_ASSERT((internal::is_same::value && internal::is_same::value), + THIS_METHOD_IS_ONLY_FOR_EXPRESSIONS_OF_BOOL); + return CwiseBinaryOp(derived(),other.derived()); +} diff --git a/test/array_for_matrix.cpp b/test/array_for_matrix.cpp index 97e03be83..c1501947b 100644 --- a/test/array_for_matrix.cpp +++ b/test/array_for_matrix.cpp @@ -134,6 +134,12 @@ template void comparisons(const MatrixType& m) // count VERIFY(((m1.array().abs()+1)>RealScalar(0.1)).count() == rows*cols); + // and/or + VERIFY( ((m1.array()RealScalar(0)).matrix()).count() == 0); + VERIFY( ((m1.array()=RealScalar(0)).matrix()).count() == rows*cols); + RealScalar a = m1.cwiseAbs().mean(); + VERIFY( ((m1.array()<-a).matrix() || (m1.array()>a).matrix()).count() == (m1.cwiseAbs().array()>a).count()); + typedef Matrix VectorOfIndices; // TODO allows colwise/rowwise for array diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 7b5f3eb38..2a3117b2b 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -217,6 +217,51 @@ template void sparse_basic(const SparseMatrixType& re refM1(it.row(), it.col()) += s1; VERIFY_IS_APPROX(m1, refM1); } + + // and/or + { + typedef SparseMatrix SpBool; + SpBool mb1 = m1.real().template cast(); + SpBool mb2 = m2.real().template cast(); + VERIFY_IS_EQUAL(mb1.template cast().sum(), refM1.real().template cast().count()); + VERIFY_IS_EQUAL((mb1 && mb2).template cast().sum(), (refM1.real().template cast() && refM2.real().template cast()).count()); + VERIFY_IS_EQUAL((mb1 || mb2).template cast().sum(), (refM1.real().template cast() || refM2.real().template cast()).count()); + SpBool mb3 = mb1 && mb2; + if(mb1.coeffs().all() && mb2.coeffs().all()) + { + VERIFY_IS_EQUAL(mb3.nonZeros(), (refM1.real().template cast() && refM2.real().template cast()).count()); + } + } + } + + // test reverse iterators + { + DenseMatrix refMat2 = DenseMatrix::Zero(rows, cols); + SparseMatrixType m2(rows, cols); + initSparse(density, refMat2, m2); + std::vector ref_value(m2.innerSize()); + std::vector ref_index(m2.innerSize()); + if(internal::random()) + m2.makeCompressed(); + for(Index j = 0; jSchedule([=, &handleRange]() { handleRange(mid, last); }); - pool_->Schedule([=, &handleRange]() { handleRange(first, mid); }); + handleRange(first, mid); }; handleRange(0, n); barrier.Wait();