Skip to content

Commit

Permalink
Fix standalone endianness macros. (#678)
Browse files Browse the repository at this point in the history
* 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 `<bit>` is missing, just in case.
* Fix the `_WIN32` definitions. All Windows platforms are little-endian
  (regardless of x86/x64/ARM/ARM64), `<boost/predef/other/endian.h>`
  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 #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.
  • Loading branch information
StephanTLavavej authored Aug 24, 2021
1 parent a4d5ae7 commit 88c4b8d
Showing 1 changed file with 16 additions and 38 deletions.
54 changes: 16 additions & 38 deletions include/boost/math/special_functions/detail/fp_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,40 @@ With these techniques, the code could be simplified.
#include <boost/math/tools/is_standalone.hpp>
#include <boost/math/tools/assert.hpp>

// Determine endinaness
// Determine endianness
#ifndef BOOST_MATH_STANDALONE

#include <boost/predef/other/endian.h>
#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(<bit>)
#include <bit>
#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 <bit> 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; }
Expand Down Expand Up @@ -243,14 +249,7 @@ template<> struct fp_traits_non_native<double, double_precision>
}

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;
};

//..............................................................................
Expand Down Expand Up @@ -303,14 +302,7 @@ template<> struct fp_traits_non_native<long double, double_precision>
}

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;
};

//..............................................................................
Expand Down Expand Up @@ -417,14 +409,7 @@ struct fp_traits_non_native<long double, extended_double_precision>
}

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;
};


Expand Down Expand Up @@ -498,14 +483,7 @@ struct fp_traits_non_native<long double, extended_double_precision>
}

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
Expand Down

0 comments on commit 88c4b8d

Please sign in to comment.