diff options
-rw-r--r-- | unsupported/Eigen/CXX11/src/Tensor/TensorMorphing.h | 12 | ||||
-rw-r--r-- | 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<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Devi } m_is_identity = true; + bool degenerate = false; for (int i = 0; i < internal::array_size<Dimensions>::value; ++i) { eigen_assert(m_impl.dimensions()[i] >= op.sizes()[i] + op.startIndices()[i]); @@ -458,6 +459,9 @@ struct TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, 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<const TensorSlicingOp<StartIndices, Sizes, ArgType>, 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<Index>(m_outputStrides[i]); - } + // NOTE: if tensor is degenerate, we send 1 to prevent TensorIntDivisor constructor crash + m_fastOutputStrides[i] = internal::TensorIntDivisor<Index>(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<const TensorSlicingOp<StartIndices, Sizes, ArgType>, 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<Index>(m_outputStrides[i]); - } + // NOTE: if tensor is degenerate, we send 1 to prevent TensorIntDivisor constructor crash + m_fastOutputStrides[i] = internal::TensorIntDivisor<Index>(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<typename T, int DataLayout> +static void test_empty_slice() +{ + Tensor<T, 3, DataLayout> tensor(2,3,5); + tensor.setRandom(); + Tensor<T, 3, DataLayout> copy = tensor; + + // empty size in first dimension + Eigen::DSizes<ptrdiff_t, 3> indices1(1,2,3); + Eigen::DSizes<ptrdiff_t, 3> sizes1(0,1,2); + Tensor<T, 3, DataLayout> slice1(0,1,2); + slice1.setRandom(); + tensor.slice(indices1, sizes1) = slice1; + + // empty size in second dimension + Eigen::DSizes<ptrdiff_t, 3> indices2(1,2,3); + Eigen::DSizes<ptrdiff_t, 3> sizes2(1,0,2); + Tensor<T, 3, DataLayout> slice2(1,0,2); + slice2.setRandom(); + tensor.slice(indices2, sizes2) = slice2; + + // empty size in third dimension + Eigen::DSizes<ptrdiff_t, 3> indices3(1,2,3); + Eigen::DSizes<ptrdiff_t, 3> sizes3(1,1,0); + Tensor<T, 3, DataLayout> slice3(1,1,0); + slice3.setRandom(); + tensor.slice(indices3, sizes3) = slice3; + + // empty size in first and second dimension + Eigen::DSizes<ptrdiff_t, 3> indices4(1,2,3); + Eigen::DSizes<ptrdiff_t, 3> sizes4(0,0,2); + Tensor<T, 3, DataLayout> slice4(0,0,2); + slice4.setRandom(); + tensor.slice(indices4, sizes4) = slice4; + + // empty size in second and third dimension + Eigen::DSizes<ptrdiff_t, 3> indices5(1,2,3); + Eigen::DSizes<ptrdiff_t, 3> sizes5(1,0,0); + Tensor<T, 3, DataLayout> slice5(1,0,0); + slice5.setRandom(); + tensor.slice(indices5, sizes5) = slice5; + + // empty size in all dimensions + Eigen::DSizes<ptrdiff_t, 3> indices6(1,2,3); + Eigen::DSizes<ptrdiff_t, 3> sizes6(0,0,0); + Tensor<T, 3, DataLayout> 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 |