From f284c8592b279d5e796842f662927c86c6bdc185 Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Wed, 24 Feb 2021 18:12:51 -0800 Subject: Don't crash when attempting to slice an empty tensor. --- .../Eigen/CXX11/src/Tensor/TensorMorphing.h | 12 +++-- unsupported/test/cxx11_tensor_morphing.cpp | 60 ++++++++++++++++++++++ 2 files changed, 68 insertions(+), 4 deletions(-) diff --git a/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h b/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h index ceecd54d0..ef79c8567 100644 --- a/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h +++ b/unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h @@ -451,6 +451,7 @@ struct TensorEvaluator, Devi } m_is_identity = true; + bool degenerate = false; for (int i = 0; i < internal::array_size::value; ++i) { eigen_assert(m_impl.dimensions()[i] >= op.sizes()[i] + op.startIndices()[i]); @@ -458,6 +459,9 @@ struct TensorEvaluator, Devi op.startIndices()[i] != 0) { m_is_identity = false; } + if (op.sizes()[i] == 0) { // we have an empty size + degenerate = true; + } } // No strides for scalars. @@ -475,8 +479,8 @@ struct TensorEvaluator, Devi m_outputStrides[0] = 1; for (int i = 1; i < NumDims; ++i) { m_outputStrides[i] = m_outputStrides[i-1] * output_dims[i-1]; - m_fastOutputStrides[i] = internal::TensorIntDivisor(m_outputStrides[i]); - } + // NOTE: if tensor is degenerate, we send 1 to prevent TensorIntDivisor constructor crash + m_fastOutputStrides[i] = internal::TensorIntDivisor(degenerate ? 1 : m_outputStrides[i]); } } else { m_inputStrides[NumDims-1] = 1; for (int i = NumDims - 2; i >= 0; --i) { @@ -487,8 +491,8 @@ struct TensorEvaluator, Devi m_outputStrides[NumDims-1] = 1; for (int i = NumDims - 2; i >= 0; --i) { m_outputStrides[i] = m_outputStrides[i+1] * output_dims[i+1]; - m_fastOutputStrides[i] = internal::TensorIntDivisor(m_outputStrides[i]); - } + // NOTE: if tensor is degenerate, we send 1 to prevent TensorIntDivisor constructor crash + m_fastOutputStrides[i] = internal::TensorIntDivisor(degenerate ? 1 : m_outputStrides[i]); } } } diff --git a/unsupported/test/cxx11_tensor_morphing.cpp b/unsupported/test/cxx11_tensor_morphing.cpp index e8c42a4cd..ed5d5ade3 100644 --- a/unsupported/test/cxx11_tensor_morphing.cpp +++ b/unsupported/test/cxx11_tensor_morphing.cpp @@ -479,6 +479,66 @@ static void test_composition() } } +template +static void test_empty_slice() +{ + Tensor tensor(2,3,5); + tensor.setRandom(); + Tensor copy = tensor; + + // empty size in first dimension + Eigen::DSizes indices1(1,2,3); + Eigen::DSizes sizes1(0,1,2); + Tensor slice1(0,1,2); + slice1.setRandom(); + tensor.slice(indices1, sizes1) = slice1; + + // empty size in second dimension + Eigen::DSizes indices2(1,2,3); + Eigen::DSizes sizes2(1,0,2); + Tensor slice2(1,0,2); + slice2.setRandom(); + tensor.slice(indices2, sizes2) = slice2; + + // empty size in third dimension + Eigen::DSizes indices3(1,2,3); + Eigen::DSizes sizes3(1,1,0); + Tensor slice3(1,1,0); + slice3.setRandom(); + tensor.slice(indices3, sizes3) = slice3; + + // empty size in first and second dimension + Eigen::DSizes indices4(1,2,3); + Eigen::DSizes sizes4(0,0,2); + Tensor slice4(0,0,2); + slice4.setRandom(); + tensor.slice(indices4, sizes4) = slice4; + + // empty size in second and third dimension + Eigen::DSizes indices5(1,2,3); + Eigen::DSizes sizes5(1,0,0); + Tensor slice5(1,0,0); + slice5.setRandom(); + tensor.slice(indices5, sizes5) = slice5; + + // empty size in all dimensions + Eigen::DSizes indices6(1,2,3); + Eigen::DSizes sizes6(0,0,0); + Tensor slice6(0,0,0); + slice6.setRandom(); + tensor.slice(indices6, sizes6) = slice6; + + // none of these operations should change the tensor's components + // because all of the rvalue slices have at least one zero dimension + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 3; ++j) { + for (int k = 0; k < 5; ++k) { + VERIFY_IS_EQUAL(tensor(i,j,k), copy(i,j,k)); + } + } + } +} + #define CALL_SUBTEST_PART(PART) \ CALL_SUBTEST_##PART -- cgit v1.2.3 From 6eebe97babeb861cff713ec290ba9c7dec89b865 Mon Sep 17 00:00:00 2001 From: Chip-Kerchner Date: Wed, 24 Feb 2021 20:43:23 -0600 Subject: Fix clang compile when no MMA flags are set. Simplify MMA compiler detection. --- Eigen/src/Core/arch/AltiVec/MatrixProduct.h | 17 +++++++++++++---- Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Eigen/src/Core/arch/AltiVec/MatrixProduct.h b/Eigen/src/Core/arch/AltiVec/MatrixProduct.h index 89d81e06f..03d474a70 100644 --- a/Eigen/src/Core/arch/AltiVec/MatrixProduct.h +++ b/Eigen/src/Core/arch/AltiVec/MatrixProduct.h @@ -12,12 +12,21 @@ #include "MatrixProductCommon.h" -#if __GNUC__ > 10 || __clang_major__ > 11 || \ - (__GNUC__ == 10 && (__GNUC_MINOR__ > 2 || \ - (__GNUC_MINOR__ == 2 && \ - __GNUC_PATCHLEVEL__ >= 1))) +#if EIGEN_COMP_LLVM +#if !defined(EIGEN_ALTIVEC_DISABLE_MMA) && !defined(EIGEN_ALTIVEC_MMA_ONLY) +#ifdef __MMA__ +#define EIGEN_ALTIVEC_MMA_ONLY +#else +#define EIGEN_ALTIVEC_DISABLE_MMA +#endif +#endif +#endif + +#ifdef __has_builtin +#if __has_builtin(__builtin_mma_assemble_acc) #define ALTIVEC_MMA_SUPPORT #endif +#endif #if defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) #include "MatrixProductMMA.h" diff --git a/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h b/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h index bfee9ee92..37db1a6f1 100644 --- a/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h +++ b/Eigen/src/Core/arch/AltiVec/MatrixProductMMA.h @@ -12,9 +12,11 @@ #pragma GCC target("cpu=power10") +#ifdef __has_builtin #if !__has_builtin(__builtin_vsx_assemble_pair) #define __builtin_vsx_assemble_pair __builtin_mma_assemble_pair #endif +#endif namespace Eigen { -- cgit v1.2.3 From ecb7b19dfa6c4bbf7a4068e114a1c86aa88908fe Mon Sep 17 00:00:00 2001 From: Antonio Sanchez Date: Thu, 25 Feb 2021 08:04:05 -0800 Subject: Disable new/delete test for HIP --- test/gpu_basic.cu | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/gpu_basic.cu b/test/gpu_basic.cu index 1935f0bc6..b2e657e72 100644 --- a/test/gpu_basic.cu +++ b/test/gpu_basic.cu @@ -409,6 +409,9 @@ EIGEN_DECLARE_TEST(gpu_basic) // (aka 'ArrayBase, -1, -1> >') has protected default constructor CALL_SUBTEST( run_and_compare_to_gpu(replicate(), nthreads, in, out) ); CALL_SUBTEST( run_and_compare_to_gpu(replicate(), nthreads, in, out) ); + + // HIP does not support new/delete on device. + CALL_SUBTEST( run_and_compare_to_gpu(alloc_new_delete(), nthreads, in, out) ); #endif CALL_SUBTEST( run_and_compare_to_gpu(redux(), nthreads, in, out) ); @@ -438,5 +441,4 @@ EIGEN_DECLARE_TEST(gpu_basic) typedef Matrix Matrix6f; CALL_SUBTEST( run_and_compare_to_gpu(eigenvalues(), nthreads, in, out) ); #endif - CALL_SUBTEST( run_and_compare_to_gpu(alloc_new_delete(), nthreads, in, out) ); } -- cgit v1.2.3 From 5297b7162a0630e2e5b1459fa665c9f3b1eb532a Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Wed, 24 Feb 2021 17:49:20 -0800 Subject: Make it possible to specify NaN propagation strategy for maxCoeff/minCoeff reductions. --- Eigen/src/Core/DenseBase.h | 5 +++++ Eigen/src/Core/Redux.h | 30 ++++++++++++++++++++++++++++++ test/array_cwise.cpp | 14 ++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index 767a8e274..c83a3fcc6 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -452,6 +452,11 @@ template class DenseBase EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const; EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const; + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const; + template + EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const; + 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..4e5affc43 100644 --- a/Eigen/src/Core/Redux.h +++ b/Eigen/src/Core/Redux.h @@ -429,6 +429,21 @@ DenseBase::minCoeff() const return derived().redux(Eigen::internal::scalar_min_op()); } +/** \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. + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar +DenseBase::minCoeff() const +{ + return derived().redux(Eigen::internal::scalar_min_op()); +} + /** \returns the maximum of all coefficients of \c *this. * \warning the matrix must be not empty, otherwise an assertion is triggered. * \warning the result is undefined if \c *this contains NaN. @@ -440,6 +455,21 @@ DenseBase::maxCoeff() const return derived().redux(Eigen::internal::scalar_max_op()); } +/** \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. + */ +template +template +EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE typename internal::traits::Scalar +DenseBase::maxCoeff() const +{ + return derived().redux(Eigen::internal::scalar_max_op()); +} + /** \returns the sum of all coefficients of \c *this * * If \c *this is empty, then the value 0 is returned. 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) -- cgit v1.2.3 From 51eba8c3e2567adbce53dfc9e62bddf294220fcc Mon Sep 17 00:00:00 2001 From: Rasmus Munk Larsen Date: Wed, 24 Feb 2021 17:59:36 -0800 Subject: Fix indentation. --- Eigen/src/Core/DenseBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Eigen/src/Core/DenseBase.h b/Eigen/src/Core/DenseBase.h index c83a3fcc6..94dddd27d 100644 --- a/Eigen/src/Core/DenseBase.h +++ b/Eigen/src/Core/DenseBase.h @@ -453,7 +453,7 @@ template class DenseBase EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const; template - EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const; + EIGEN_DEVICE_FUNC typename internal::traits::Scalar minCoeff() const; template EIGEN_DEVICE_FUNC typename internal::traits::Scalar maxCoeff() const; -- cgit v1.2.3