diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 767a8e274..20cc4821a 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -449,9 +449,23 @@ template class DenseBase EIGEN_DEVICE_FUNC Scalar prod() const; + template EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const; + template EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const; + + // By default, the fastest version with undefined NaN propagation semantics is + // used. + // TODO(rmlarsen): Replace with default template argument when we move to + // c++11 or beyond. + EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const { + return minCoeff(); + } + EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const { + return maxCoeff(); + } + template EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff(IndexType* row, IndexType* col) const; template EIGEN_DEVICE_FUNC diff --git a/Eigen/src/Core/Redux.h b/Eigen/src/Core/Redux.h index 2eef5abc5..30598f415 100644 --- a/Eigen/src/Core/Redux.h +++ b/Eigen/src/Core/Redux.h @@ -419,25 +419,33 @@ DenseBase::redux(const Func& func) const } /** \returns the minimum of all coefficients of \c *this. + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is minimum of elements that are not NaN * \warning the matrix must be not empty, otherwise an assertion is triggered. - * \warning the result is undefined if \c *this contains NaN. */ template +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::minCoeff() const { - return derived().redux(Eigen::internal::scalar_min_op()); + return derived().redux(Eigen::internal::scalar_min_op()); } -/** \returns the maximum of all coefficients of \c *this. +/** \returns the maximum of all coefficients of \c *this. + * In case \c *this contains NaN, NaNPropagation determines the behavior: + * NaNPropagation == PropagateFast : undefined + * NaNPropagation == PropagateNaN : result is NaN + * NaNPropagation == PropagateNumbers : result is maximum of elements that are not NaN * \warning the matrix must be not empty, otherwise an assertion is triggered. - * \warning the result is undefined if \c *this contains NaN. */ template +template EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar DenseBase::maxCoeff() const { - return derived().redux(Eigen::internal::scalar_max_op()); + return derived().redux(Eigen::internal::scalar_max_op()); } /** \returns the sum of all coefficients of \c *this diff --git a/test/array_cwise.cpp b/test/array_cwise.cpp index 7f7e44f89..92abf6968 100644 --- a/test/array_cwise.cpp +++ b/test/array_cwise.cpp @@ -610,6 +610,20 @@ template void min_max(const ArrayType& m) VERIFY_IS_APPROX(ArrayType::Constant(rows,cols, maxM1), (m1.max)( maxM1)); VERIFY_IS_APPROX(m1, (m1.max)( minM1)); + + // min/max with various NaN propagation options. + if (m1.size() > 1 && !NumTraits::IsInteger) { + m1(0,0) = std::numeric_limits::quiet_NaN(); + maxM1 = m1.template maxCoeff(); + minM1 = m1.template minCoeff(); + VERIFY((numext::isnan)(maxM1)); + VERIFY((numext::isnan)(minM1)); + + maxM1 = m1.template maxCoeff(); + minM1 = m1.template minCoeff(); + VERIFY(!(numext::isnan)(maxM1)); + VERIFY(!(numext::isnan)(minM1)); + } } EIGEN_DECLARE_TEST(array_cwise)