diff --git a/math_private.h b/math_private.h
--- a/math_private.h
+++ b/math_private.h
@@ -12,19 +12,19 @@
 /*
  * from: @(#)fdlibm.h 5.1 93/09/24
  * $FreeBSD$
  */
 
 #ifndef _MATH_PRIVATE_H_
 #define	_MATH_PRIVATE_H_
 
+#include <bit>
 #include <stdint.h>
 #include <sys/types.h>
-#include <machine/endian.h>
 
 #include "fdlibm.h"
 
 /*
  * The original fdlibm code used statements like:
  *	n0 = ((*(int*)&one)>>29)^1;		* index of high word *
  *	ix0 = *(n0+(int*)&x);			* high word of x *
  *	ix1 = *((1-n0)+(int*)&x);		* low word of x *
@@ -36,102 +36,50 @@
  * endianness at run time.
  */
 
 /*
  * A union which permits us to convert between a double and two 32 bit
  * ints.
  */
 
-#ifdef __arm__
-#if defined(__VFP_FP__) || defined(__ARM_EABI__)
-#define	IEEE_WORD_ORDER	BYTE_ORDER
-#else
-#define	IEEE_WORD_ORDER	BIG_ENDIAN
-#endif
-#else /* __arm__ */
-#define	IEEE_WORD_ORDER	BYTE_ORDER
-#endif
-
-/* A union which permits us to convert between a long double and
-   four 32 bit ints.  */
-
-#if IEEE_WORD_ORDER == BIG_ENDIAN
+namespace detail {
+template <std::endian endianness>
+union ieee_double_shape_type;
 
-typedef union
-{
-  long double value;
-  struct {
-    u_int32_t mswhi;
-    u_int32_t mswlo;
-    u_int32_t lswhi;
-    u_int32_t lswlo;
-  } parts32;
-  struct {
-    u_int64_t msw;
-    u_int64_t lsw;
-  } parts64;
-} ieee_quad_shape_type;
-
-#endif
-
-#if IEEE_WORD_ORDER == LITTLE_ENDIAN
-
-typedef union
-{
-  long double value;
-  struct {
-    u_int32_t lswlo;
-    u_int32_t lswhi;
-    u_int32_t mswlo;
-    u_int32_t mswhi;
-  } parts32;
-  struct {
-    u_int64_t lsw;
-    u_int64_t msw;
-  } parts64;
-} ieee_quad_shape_type;
-
-#endif
-
-#if IEEE_WORD_ORDER == BIG_ENDIAN
-
-typedef union
-{
+template <>
+union ieee_double_shape_type<std::endian::big> {
   double value;
   struct
   {
     u_int32_t msw;
     u_int32_t lsw;
   } parts;
   struct
   {
     u_int64_t w;
   } xparts;
-} ieee_double_shape_type;
-
-#endif
+};
 
-#if IEEE_WORD_ORDER == LITTLE_ENDIAN
-
-typedef union
-{
+template <>
+union ieee_double_shape_type<std::endian::little> {
   double value;
   struct
   {
     u_int32_t lsw;
     u_int32_t msw;
   } parts;
   struct
   {
     u_int64_t w;
   } xparts;
-} ieee_double_shape_type;
+};
+}
 
-#endif
+using ieee_double_shape_type = detail::ieee_double_shape_type<std::endian::native>;
 
 /* Get two 32 bit ints from a double.  */
 
 #define EXTRACT_WORDS(ix0,ix1,d)				\
 do {								\
   ieee_double_shape_type ew_u;					\
   ew_u.value = (d);						\
   (ix0) = ew_u.parts.msw;					\
