2

Using Eigen's unsupported Tensor module, if I do:

    size_t dim0 = 3;
    size_t dim1 = 2;
    size_t dim2 = 4;
    Eigen::Tensor<double, 3> var(dim0, dim1, dim2);

I get the following error:

/usr/local/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorDimensions.h:287:167: error: non-constant-expression cannot be narrowed from type 'unsigned long' to 'std::__1::array<long, 3>::value_type' (aka 'long') in initializer list [-Wc++11-narrowing]

But the code compiles OK if I explicitly cast the dimensions to long int:

    long int dim0 = 3;
    long int dim1 = 2;
    long int dim2 = 4;
    Eigen::Tensor<double, 3> var(dim0, dim1, dim2);

Questions:

  1. For what size variable will this become unsafe? If at all?
  2. Surely Eigen should be generally accepting a (size_t) type as a dimension argument? Should I file a bug report for this or is it intended behaviour here?

I'm using C++11, clang on Mac OSX (haven't tested other platforms).

thclark
  • 4,784
  • 3
  • 39
  • 65
  • 1
    `size_t` for length is not a great idea, the proper types are signed ones for optimization/UB reasons. – Matthieu Brucher Jan 17 '19 at 09:54
  • Wow, I didn't know that, thank you @Matthieu. For Eigen in general, or just Tensors? And is there an example somewhere of how having a signed tensor dimension can help optimise (it's not intuitive that a tensor dimension could be negative)? – thclark Jan 17 '19 at 09:59
  • 1
    @thclark In short: Unsigned integers must "wrap around" whereas signed ones are (allowed to be) UB on overflow. The `i < length` check in a `for` loop where `i++` happens every iteration becomes simpler when you can be sure that `i++` never decreases `i` (which might happen from unsigned wraparound). Just one instance where UB gives the compiler better optimization opportunities. – Max Langhof Jan 17 '19 at 10:13
  • Ah, yeah that makes sense. Thank you @Max – thclark Jan 17 '19 at 11:43
  • 1
    @MatthieuBrucher Could you check [my question](https://stackoverflow.com/questions/54243601) on your comment? – Costantino Grana Jan 17 '19 at 20:34
  • If `i++` really decreases `i` due to wrap around, the condition `i – Weijun Zhou Oct 27 '21 at 10:41

1 Answers1

5

The narrowing warning will appear for any type that cannot be converted to a long without loss. So that means size_t, but also long long on some platforms.

In general, loop indices should be signed, hence Eigen decision to store long for sizes.

For more info on this, there are some cppcon topics (Chandler Carruth, mainly) about undefined behavior that help the compiler.

Matthieu Brucher
  • 21,634
  • 7
  • 38
  • 62
  • OK, so the answers are 1) I should be typecasting to a signed type, checking that this doesn't cause an overflow error. and 2) it's valid and expected that the size arguments to Eigen::tensor are signed, so I shouldn't submit a bug report. – thclark Jan 17 '19 at 10:05
  • 2
    Exactly, yes. Perfectly valid warning due to how Eigen works (at least that's my opinion). – Matthieu Brucher Jan 17 '19 at 10:06