mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-11 19:29:02 +08:00
Don't crash when attempting to slice an empty tensor.
This commit is contained in:
parent
113e61f364
commit
f284c8592b
@ -451,6 +451,7 @@ struct TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Devi
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_is_identity = true;
|
m_is_identity = true;
|
||||||
|
bool degenerate = false;
|
||||||
for (int i = 0; i < internal::array_size<Dimensions>::value; ++i) {
|
for (int i = 0; i < internal::array_size<Dimensions>::value; ++i) {
|
||||||
eigen_assert(m_impl.dimensions()[i] >=
|
eigen_assert(m_impl.dimensions()[i] >=
|
||||||
op.sizes()[i] + op.startIndices()[i]);
|
op.sizes()[i] + op.startIndices()[i]);
|
||||||
@ -458,6 +459,9 @@ struct TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Devi
|
|||||||
op.startIndices()[i] != 0) {
|
op.startIndices()[i] != 0) {
|
||||||
m_is_identity = false;
|
m_is_identity = false;
|
||||||
}
|
}
|
||||||
|
if (op.sizes()[i] == 0) { // we have an empty size
|
||||||
|
degenerate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No strides for scalars.
|
// No strides for scalars.
|
||||||
@ -475,8 +479,8 @@ struct TensorEvaluator<const TensorSlicingOp<StartIndices, Sizes, ArgType>, Devi
|
|||||||
m_outputStrides[0] = 1;
|
m_outputStrides[0] = 1;
|
||||||
for (int i = 1; i < NumDims; ++i) {
|
for (int i = 1; i < NumDims; ++i) {
|
||||||
m_outputStrides[i] = m_outputStrides[i-1] * output_dims[i-1];
|
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 {
|
} else {
|
||||||
m_inputStrides[NumDims-1] = 1;
|
m_inputStrides[NumDims-1] = 1;
|
||||||
for (int i = NumDims - 2; i >= 0; --i) {
|
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;
|
m_outputStrides[NumDims-1] = 1;
|
||||||
for (int i = NumDims - 2; i >= 0; --i) {
|
for (int i = NumDims - 2; i >= 0; --i) {
|
||||||
m_outputStrides[i] = m_outputStrides[i+1] * output_dims[i+1];
|
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]); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) \
|
#define CALL_SUBTEST_PART(PART) \
|
||||||
CALL_SUBTEST_##PART
|
CALL_SUBTEST_##PART
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user