From 88c4b8d661dbe15be7317f04f1eccae0c9c39980 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 24 Aug 2021 07:36:43 -0700 Subject: [PATCH] Fix standalone endianness macros. (#678) * Fix comment typos: "endinaness" to "endianness" * Change the C++20 checks (for both `__cplusplus` and `_MSVC_LANG`) to be strict: `> 202000L` to `>= 202002L` * Add an `#error` when C++20 `` is missing, just in case. * Fix the `_WIN32` definitions. All Windows platforms are little-endian (regardless of x86/x64/ARM/ARM64), `` correctly reports little-endian, and MSVC's STL simply hardcodes `enum class endian { little = 0, big = 1, native = little };`, see https://github.com/microsoft/STL/blob/f75c7f596c7b491168fefb5eff5164ab7ae36867/stl/inc/bit#L271 . * Add a `static_assert` to verify that exactly one of `BOOST_MATH_ENDIAN_BIG_BYTE` or `BOOST_MATH_ENDIAN_LITTLE_BYTE` is true. This avoids the need for "Endian type could not be identified" consistency checks below. * Fix boostorg/math#677 by not testing `BOOST_MATH_ENDIAN_BIG_BYTE` and `BOOST_MATH_ENDIAN_LITTLE_BYTE` with the preprocessor, as `std::endian::native` isn't a preprocessor constant. Now, this simply expects `BOOST_MATH_ENDIAN_BIG_BYTE` to be usable in a constant expression, and assumes (due to the consistency check above) that if we aren't big-endian, we must be little-endian. --- .../special_functions/detail/fp_traits.hpp | 54 ++++++------------- 1 file changed, 16 insertions(+), 38 deletions(-) diff --git a/include/boost/math/special_functions/detail/fp_traits.hpp b/include/boost/math/special_functions/detail/fp_traits.hpp index 38041d3e7e..fcc3aab893 100644 --- a/include/boost/math/special_functions/detail/fp_traits.hpp +++ b/include/boost/math/special_functions/detail/fp_traits.hpp @@ -27,34 +27,40 @@ With these techniques, the code could be simplified. #include #include -// Determine endinaness +// Determine endianness #ifndef BOOST_MATH_STANDALONE #include #define BOOST_MATH_ENDIAN_BIG_BYTE BOOST_ENDIAN_BIG_BYTE #define BOOST_MATH_ENDIAN_LITTLE_BYTE BOOST_ENDIAN_LITTLE_BYTE -#elif (__cplusplus > 202000L || _MSVC_LANG > 202000L) +#elif (__cplusplus >= 202002L || _MSVC_LANG >= 202002L) #if __has_include() #include #define BOOST_MATH_ENDIAN_BIG_BYTE (std::endian::native == std::endian::big) #define BOOST_MATH_ENDIAN_LITTLE_BYTE (std::endian::native == std::endian::little) +#else +#error Missing header. Please disable standalone mode, and file an issue at https://github.com/boostorg/math #endif #elif defined(_WIN32) -#define BOOST_MATH_ENDIAN_BIG_BYTE 1 -#define BOOST_MATH_ENDIAN_LITTLE_BYTE 0 +#define BOOST_MATH_ENDIAN_BIG_BYTE 0 +#define BOOST_MATH_ENDIAN_LITTLE_BYTE 1 #elif defined(__BYTE_ORDER__) #define BOOST_MATH_ENDIAN_BIG_BYTE (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) #define BOOST_MATH_ENDIAN_LITTLE_BYTE (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#else +#else #error Could not determine endian type. Please disable standalone mode, and file an issue at https://github.com/boostorg/math -#endif // Determine endinaness +#endif // Determine endianness + +static_assert((BOOST_MATH_ENDIAN_BIG_BYTE || BOOST_MATH_ENDIAN_LITTLE_BYTE) + && !(BOOST_MATH_ENDIAN_BIG_BYTE && BOOST_MATH_ENDIAN_LITTLE_BYTE), + "Inconsistent endianness detected. Please disable standalone mode, and file an issue at https://github.com/boostorg/math"); #ifdef BOOST_NO_STDC_NAMESPACE namespace std{ using ::memcpy; } @@ -243,14 +249,7 @@ template<> struct fp_traits_non_native } private: - -#if BOOST_MATH_ENDIAN_BIG_BYTE - static constexpr int offset_ = 0; -#elif BOOST_MATH_ENDIAN_LITTLE_BYTE - static constexpr int offset_ = 4; -#else - static_assert(sizeof(double_precision) == 0, "Endian type could not be identified"); -#endif + static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 4; }; //.............................................................................. @@ -303,14 +302,7 @@ template<> struct fp_traits_non_native } private: - -#if BOOST_MATH_ENDIAN_BIG_BYTE - static constexpr int offset_ = 0; -#elif BOOST_MATH_ENDIAN_LITTLE_BYTE - static constexpr int offset_ = 4; -#else - static_assert(sizeof(double_precision) == 0, "Endian type could not be identified"); -#endif + static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 4; }; //.............................................................................. @@ -417,14 +409,7 @@ struct fp_traits_non_native } private: - -#if BOOST_MATH_ENDIAN_BIG_BYTE - static constexpr int offset_ = 0; -#elif BOOST_MATH_ENDIAN_LITTLE_BYTE - static constexpr int offset_ = 12; -#else - static_assert(sizeof(extended_double_precision) == 0, "Endian type could not be identified"); -#endif + static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12; }; @@ -498,14 +483,7 @@ struct fp_traits_non_native } private: - -#if BOOST_MATH_ENDIAN_BIG_BYTE - static constexpr int offset_ = 0; -#elif BOOST_MATH_ENDIAN_LITTLE_BYTE - static constexpr int offset_ = 12; -#else - static_assert(sizeof(extended_double_precision) == 0, "Endian type could not be identified"); -#endif + static constexpr int offset_ = BOOST_MATH_ENDIAN_BIG_BYTE ? 0 : 12; }; #endif