Fix conversion of `Eigen::half` to `_Float16` in AVX512 code
Reference issue
Fixes #2835 (closed)
Enhancement over !1647 (closed) to avoid potential ODR issues caused by partial availability of the _Float16 conversion on e.g. GCC <= 12 that allows a static_cast<_Float16> using the float conversion operator.
Inlined the bit_cast to call sites after discussion about confusion with std::float16_t
What does this implement/fix?
Fix compilation on AVX512FP16. A cast from or to an extended floating point type is only implicit when the conversion is non-lossy.
This affects Eigen::half which has an implicit float conversion operator but is passed to functions expecting a _Float16 or cast into that, i.e. static_cast<_Float16>(halfInstance). This is disallowed by the (proposed) C++ standard and seemingly enforced in GCC 13 where such code fails to compile.
The solution proposed here is an explicit _Float16 conversion function as_float16
Naming as_ because the conversion is lossless and optimized to a no-op in assembly.
is to convert the (binary compatible) Eigen::Half to _Float16 via bit_cast.
Similarly float or even double constants are used as input to intrinsics expecting a _Float16 which is also not allowed. Currently this results in warnings such as
warning: ISO C++ does not allow converting to '_Float16' from 'float' with greater conversion rank [-Wnarrowing]
But that likely will be a hard error according to the wording. See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1467r4.html#implicit and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112498
Hence use namespace scoped user defined literals for specifying half-precision constants.