vectorclass / version2

Vector class library, latest version
Apache License 2.0
1.31k stars 148 forks source link

Consider supporting `constexpr` to a greater extent for C++2a #11

Closed jeremyong closed 5 years ago

jeremyong commented 5 years ago

C++2a isn't yet out, but some of us are beginning to work with it and one notable feature now available in GCC 10 and clang trunk is http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1668r1.html

To summarize, the feature enables code like the following:

 constexpr double fma(double b, double c, double d) {
  if (std::is_constant_evaluated())
   return b * c + d;
  asm("vfmadd132sd %0 %1 %2"
   : "+x"(b)
   : "x" (c), "x" (d)
   );
  return b;
 }

Existing functions not marked constexpr may not benefit from constant evaluation, but more importantly, the results may not be used in constant expressions (template parameters, array sizes, etc), even if the inputs are known to be constant-evaluated.

Are there any plans to make the library more constexpr friendly in the future or is any help needed in this regard?

AgnerF commented 5 years ago

We really want something that checks whether function arguments are constants. This would be useful for the pow function and for division of an integer vector by a constant. Unfortunately, this new feature doesn't really do what we want. Suppose we make a pow function with this feature.

Vec4f pow(Vec4f x, const int n) {
   if (is_constant_evaluated()) ... // compile time branch
   else ...// runtime branch
}

// Now, this call will not use the compile time branch:
Vec4f a, b;
a = pow(b,3);

// This call will probably use the compile time branch
const Vec4f c = pow(b,3);
c += 4;  // illegal

// The above requires that the programmer is aware of the possibility of a
// faster compile time implementation, so it is no better than the present:
c = pow_const(b,3);
c += 4;  // legal
jeremyong commented 5 years ago

Yes the constexpr argument would be great and I believe is on deck for C++23. What std::is_constant_evaluated would allow though is something like

constexpr Vec4f a = pow(/* constant expression /*);
Foo<a[0]> foo;
// or
int bar[a[1]];

More generally, the operation may be part of a more complex user-defined function that may benefit from having both compile-time and a runtime capabilities. Having the constexpr friendly branch would facilitate streamlining code in areas where a compile time constant is needed (without needing to duplicate the code to perform the same computation without use of the vector lib). Thoughts?