Core: Define binary_floating_point_traits constants out of class for C++14 libeigen/eigen!3356 Co-authored-by: Rasmus Munk Larsen <rmlarsen@gmail.com>
diff --git a/Eigen/src/Core/MathFunctions.h b/Eigen/src/Core/MathFunctions.h index cf0976b..ed5ef5e 100644 --- a/Eigen/src/Core/MathFunctions.h +++ b/Eigen/src/Core/MathFunctions.h
@@ -1114,6 +1114,27 @@ EIGEN_DEVICE_FUNC static EIGEN_STRONG_INLINE Bits magnitude(const Scalar& value) { return bits(value) & ~kSignBit; } }; +// Redundant out-of-class definitions are required pre-C++17 but deprecated since. +#if EIGEN_COMP_CXXVER < 17 +template <typename Scalar> +constexpr int binary_floating_point_traits<Scalar>::kFractionBits; +template <typename Scalar> +constexpr int binary_floating_point_traits<Scalar>::kExponentBits; +template <typename Scalar> +constexpr int binary_floating_point_traits<Scalar>::kExponentBias; +template <typename Scalar> +constexpr typename binary_floating_point_traits<Scalar>::Bits binary_floating_point_traits<Scalar>::kSignBit; +template <typename Scalar> +constexpr typename binary_floating_point_traits<Scalar>::Bits binary_floating_point_traits<Scalar>::kExponentUnit; +template <typename Scalar> +constexpr typename binary_floating_point_traits<Scalar>::Bits binary_floating_point_traits<Scalar>::kFractionMask; +template <typename Scalar> +constexpr typename binary_floating_point_traits<Scalar>::Bits binary_floating_point_traits<Scalar>::kExponentMask; +template <typename Scalar> +constexpr + typename binary_floating_point_traits<Scalar>::Bits binary_floating_point_traits<Scalar>::kMaxFiniteExponentBits; +#endif + template <typename Scalar> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE bool is_exactly_zero_no_flush_impl(const Scalar& value, false_type) { return numext::is_exactly_zero(value);
diff --git a/test/numext.cpp b/test/numext.cpp index 5098c83..0373d13 100644 --- a/test/numext.cpp +++ b/test/numext.cpp
@@ -1000,6 +1000,31 @@ } } +// Stores the address of value, so a static data member passed here is odr-used at every optimization level. +template <typename T> +T read_through_address(const T& value) { + const T* volatile address = &value; + return *address; +} + +// In C++14 this links only with the out-of-class definitions of the constants. +template <typename Scalar> +void check_binary_floating_point_traits_odr_use() { + using Binary = internal::binary_floating_point_traits<Scalar>; + using Bits = typename Binary::Bits; + const Bits minBits = numext::bit_cast<Bits>((std::numeric_limits<Scalar>::min)()); + const Bits infinityBits = numext::bit_cast<Bits>(std::numeric_limits<Scalar>::infinity()); + VERIFY_IS_EQUAL(read_through_address(Binary::kFractionBits), std::numeric_limits<Scalar>::digits - 1); + VERIFY_IS_EQUAL(read_through_address(Binary::kExponentBits), + int(sizeof(Scalar) * CHAR_BIT) - std::numeric_limits<Scalar>::digits); + VERIFY_IS_EQUAL(read_through_address(Binary::kExponentBias), std::numeric_limits<Scalar>::max_exponent - 1); + VERIFY_IS_EQUAL(read_through_address(Binary::kSignBit), numext::bit_cast<Bits>(-Scalar(0))); + VERIFY_IS_EQUAL(read_through_address(Binary::kExponentUnit), minBits); + VERIFY_IS_EQUAL(read_through_address(Binary::kFractionMask), Bits(minBits - 1)); + VERIFY_IS_EQUAL(read_through_address(Binary::kExponentMask), infinityBits); + VERIFY_IS_EQUAL(read_through_address(Binary::kMaxFiniteExponentBits), Bits(infinityBits - minBits)); +} + template <typename Scalar> EIGEN_DONT_INLINE void check_binary_sign_no_flush_values() { using Binary = internal::binary_floating_point_traits<Scalar>; @@ -1244,6 +1269,10 @@ CALL_SUBTEST(check_zero_no_flush<float>()); CALL_SUBTEST(check_zero_no_flush<double>()); CALL_SUBTEST(check_zero_no_flush_custom_scalar()); + CALL_SUBTEST(check_binary_floating_point_traits_odr_use<half>()); + CALL_SUBTEST(check_binary_floating_point_traits_odr_use<bfloat16>()); + CALL_SUBTEST(check_binary_floating_point_traits_odr_use<float>()); + CALL_SUBTEST(check_binary_floating_point_traits_odr_use<double>()); CALL_SUBTEST(check_binary_sign_no_flush<float>()); CALL_SUBTEST(check_binary_sign_no_flush<double>());