math: add asuint, asuint64, asfloat and asdouble
authorSzabolcs Nagy <nsz@port70.net>
Sat, 21 Oct 2017 21:09:02 +0000 (21:09 +0000)
committerRich Felker <dalias@aerifal.cx>
Wed, 17 Apr 2019 17:04:28 +0000 (13:04 -0400)
Code generation for SET_HIGH_WORD slightly changes, but it only affects
pow, otherwise the generated code is unchanged.

src/internal/libm.h

index 6e2d190..098c705 100644 (file)
@@ -83,73 +83,55 @@ union ldshape {
        }                                         \
 } while(0)
 
+#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i
+#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f
+#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i
+#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f
+
 /* Get two 32 bit ints from a double.  */
 #define EXTRACT_WORDS(hi,lo,d)                    \
 do {                                              \
-  union {double f; uint64_t i;} __u;              \
-  __u.f = (d);                                    \
-  (hi) = __u.i >> 32;                             \
-  (lo) = (uint32_t)__u.i;                         \
+  uint64_t __u = asuint64(d);                     \
+  (hi) = __u >> 32;                               \
+  (lo) = (uint32_t)__u;                           \
 } while (0)
 
 /* Get the more significant 32 bit int from a double.  */
 #define GET_HIGH_WORD(hi,d)                       \
 do {                                              \
-  union {double f; uint64_t i;} __u;              \
-  __u.f = (d);                                    \
-  (hi) = __u.i >> 32;                             \
+  (hi) = asuint64(d) >> 32;                       \
 } while (0)
 
 /* Get the less significant 32 bit int from a double.  */
 #define GET_LOW_WORD(lo,d)                        \
 do {                                              \
-  union {double f; uint64_t i;} __u;              \
-  __u.f = (d);                                    \
-  (lo) = (uint32_t)__u.i;                         \
+  (lo) = (uint32_t)asuint64(d);                   \
 } while (0)
 
 /* Set a double from two 32 bit ints.  */
 #define INSERT_WORDS(d,hi,lo)                     \
 do {                                              \
-  union {double f; uint64_t i;} __u;              \
-  __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo);  \
-  (d) = __u.f;                                    \
+  (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \
 } while (0)
 
 /* Set the more significant 32 bits of a double from an int.  */
 #define SET_HIGH_WORD(d,hi)                       \
-do {                                              \
-  union {double f; uint64_t i;} __u;              \
-  __u.f = (d);                                    \
-  __u.i &= 0xffffffff;                            \
-  __u.i |= (uint64_t)(hi) << 32;                  \
-  (d) = __u.f;                                    \
-} while (0)
+  INSERT_WORDS(d, hi, (uint32_t)asuint64(d))
 
 /* Set the less significant 32 bits of a double from an int.  */
 #define SET_LOW_WORD(d,lo)                        \
-do {                                              \
-  union {double f; uint64_t i;} __u;              \
-  __u.f = (d);                                    \
-  __u.i &= 0xffffffff00000000ull;                 \
-  __u.i |= (uint32_t)(lo);                        \
-  (d) = __u.f;                                    \
-} while (0)
+  INSERT_WORDS(d, asuint64(d)>>32, lo)
 
 /* Get a 32 bit int from a float.  */
 #define GET_FLOAT_WORD(w,d)                       \
 do {                                              \
-  union {float f; uint32_t i;} __u;               \
-  __u.f = (d);                                    \
-  (w) = __u.i;                                    \
+  (w) = asuint(d);                                \
 } while (0)
 
 /* Set a float from a 32 bit int.  */
 #define SET_FLOAT_WORD(d,w)                       \
 do {                                              \
-  union {float f; uint32_t i;} __u;               \
-  __u.i = (w);                                    \
-  (d) = __u.f;                                    \
+  (d) = asfloat(w);                               \
 } while (0)
 
 /* fdlibm kernel functions */