math: cosmetic cleanup (use explicit union instead of fshape and dshape)

This commit is contained in:
Szabolcs Nagy
2013-09-04 17:36:00 +00:00
parent 63b9cc7773
commit 8dba548628
11 changed files with 140 additions and 166 deletions

View File

@ -21,16 +21,6 @@
#include "libc.h" #include "libc.h"
union fshape {
float value;
uint32_t bits;
};
union dshape {
double value;
uint64_t bits;
};
#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN
union ldshape { union ldshape {
@ -74,70 +64,70 @@ union ldshape {
/* Get two 32 bit ints from a double. */ /* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS(hi,lo,d) \ #define EXTRACT_WORDS(hi,lo,d) \
do { \ do { \
union dshape __u; \ union {double f; uint64_t i;} __u; \
__u.value = (d); \ __u.f = (d); \
(hi) = __u.bits >> 32; \ (hi) = __u.i >> 32; \
(lo) = (uint32_t)__u.bits; \ (lo) = (uint32_t)__u.i; \
} while (0) } while (0)
/* Get the more significant 32 bit int from a double. */ /* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD(i,d) \ #define GET_HIGH_WORD(hi,d) \
do { \ do { \
union dshape __u; \ union {double f; uint64_t i;} __u; \
__u.value = (d); \ __u.f = (d); \
(i) = __u.bits >> 32; \ (hi) = __u.i >> 32; \
} while (0) } while (0)
/* Get the less significant 32 bit int from a double. */ /* Get the less significant 32 bit int from a double. */
#define GET_LOW_WORD(i,d) \ #define GET_LOW_WORD(lo,d) \
do { \ do { \
union dshape __u; \ union {double f; uint64_t i;} __u; \
__u.value = (d); \ __u.f = (d); \
(i) = (uint32_t)__u.bits; \ (lo) = (uint32_t)__u.i; \
} while (0) } while (0)
/* Set a double from two 32 bit ints. */ /* Set a double from two 32 bit ints. */
#define INSERT_WORDS(d,hi,lo) \ #define INSERT_WORDS(d,hi,lo) \
do { \ do { \
union dshape __u; \ union {double f; uint64_t i;} __u; \
__u.bits = ((uint64_t)(hi) << 32) | (uint32_t)(lo); \ __u.i = ((uint64_t)(hi)<<32) | (uint32_t)(lo); \
(d) = __u.value; \ (d) = __u.f; \
} while (0) } while (0)
/* Set the more significant 32 bits of a double from an int. */ /* Set the more significant 32 bits of a double from an int. */
#define SET_HIGH_WORD(d,hi) \ #define SET_HIGH_WORD(d,hi) \
do { \ do { \
union dshape __u; \ union {double f; uint64_t i;} __u; \
__u.value = (d); \ __u.f = (d); \
__u.bits &= 0xffffffff; \ __u.i &= 0xffffffff; \
__u.bits |= (uint64_t)(hi) << 32; \ __u.i |= (uint64_t)(hi) << 32; \
(d) = __u.value; \ (d) = __u.f; \
} while (0) } while (0)
/* Set the less significant 32 bits of a double from an int. */ /* Set the less significant 32 bits of a double from an int. */
#define SET_LOW_WORD(d,lo) \ #define SET_LOW_WORD(d,lo) \
do { \ do { \
union dshape __u; \ union {double f; uint64_t i;} __u; \
__u.value = (d); \ __u.f = (d); \
__u.bits &= 0xffffffff00000000ull; \ __u.i &= 0xffffffff00000000ull; \
__u.bits |= (uint32_t)(lo); \ __u.i |= (uint32_t)(lo); \
(d) = __u.value; \ (d) = __u.f; \
} while (0) } while (0)
/* Get a 32 bit int from a float. */ /* Get a 32 bit int from a float. */
#define GET_FLOAT_WORD(i,d) \ #define GET_FLOAT_WORD(w,d) \
do { \ do { \
union fshape __u; \ union {float f; uint32_t i;} __u; \
__u.value = (d); \ __u.f = (d); \
(i) = __u.bits; \ (w) = __u.i; \
} while (0) } while (0)
/* Set a float from a 32 bit int. */ /* Set a float from a 32 bit int. */
#define SET_FLOAT_WORD(d,i) \ #define SET_FLOAT_WORD(d,w) \
do { \ do { \
union fshape __u; \ union {float f; uint32_t i;} __u; \
__u.bits = (i); \ __u.i = (w); \
(d) = __u.value; \ (d) = __u.f; \
} while (0) } while (0)
/* fdlibm kernel functions */ /* fdlibm kernel functions */

View File

@ -1,10 +1,11 @@
#include "libm.h" #include <math.h>
#include <stdint.h>
int __fpclassify(double x) int __fpclassify(double x)
{ {
union dshape u = { x }; union {double f; uint64_t i;} u = {x};
int e = u.bits>>52 & 0x7ff; int e = u.i>>52 & 0x7ff;
if (!e) return u.bits<<1 ? FP_SUBNORMAL : FP_ZERO; if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO;
if (e==0x7ff) return u.bits<<12 ? FP_NAN : FP_INFINITE; if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE;
return FP_NORMAL; return FP_NORMAL;
} }

View File

@ -1,10 +1,11 @@
#include "libm.h" #include <math.h>
#include <stdint.h>
int __fpclassifyf(float x) int __fpclassifyf(float x)
{ {
union fshape u = { x }; union {float f; uint32_t i;} u = {x};
int e = u.bits>>23 & 0xff; int e = u.i>>23 & 0xff;
if (!e) return u.bits<<1 ? FP_SUBNORMAL : FP_ZERO; if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO;
if (e==0xff) return u.bits<<9 ? FP_NAN : FP_INFINITE; if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE;
return FP_NORMAL; return FP_NORMAL;
} }

View File

@ -1,11 +1,8 @@
#include "libm.h" #include "libm.h"
double copysign(double x, double y) { double copysign(double x, double y) {
union dshape ux, uy; union {double f; uint64_t i;} ux={x}, uy={y};
ux.i &= -1ULL/2;
ux.value = x; ux.i |= uy.i & 1ULL<<63;
uy.value = y; return ux.f;
ux.bits &= (uint64_t)-1>>1;
ux.bits |= uy.bits & (uint64_t)1<<63;
return ux.value;
} }

View File

@ -1,11 +1,10 @@
#include "libm.h" #include <math.h>
#include <stdint.h>
float copysignf(float x, float y) { float copysignf(float x, float y)
union fshape ux, uy; {
union {float f; uint32_t i;} ux={x}, uy={y};
ux.value = x; ux.i &= 0x7fffffff;
uy.value = y; ux.i |= uy.i & 0x80000000;
ux.bits &= (uint32_t)-1>>1; return ux.f;
ux.bits |= uy.bits & (uint32_t)1<<31;
return ux.value;
} }

View File

@ -1,10 +1,9 @@
#include "libm.h" #include <math.h>
#include <stdint.h>
double fabs(double x) double fabs(double x)
{ {
union dshape u; union {double f; uint64_t i;} u = {x};
u.i &= -1ULL/2;
u.value = x; return u.f;
u.bits &= (uint64_t)-1 / 2;
return u.value;
} }

View File

@ -1,10 +1,9 @@
#include "libm.h" #include <math.h>
#include <stdint.h>
float fabsf(float x) float fabsf(float x)
{ {
union fshape u; union {float f; uint32_t i;} u = {x};
u.i &= 0x7fffffff;
u.value = x; return u.f;
u.bits &= (uint32_t)-1 / 2;
return u.value;
} }

View File

@ -1,35 +1,31 @@
#include "libm.h" #include "libm.h"
#define SIGN ((uint64_t)1<<63)
double nextafter(double x, double y) double nextafter(double x, double y)
{ {
union dshape ux, uy; union {double f; uint64_t i;} ux={x}, uy={y};
uint64_t ax, ay; uint64_t ax, ay;
int e; int e;
if (isnan(x) || isnan(y)) if (isnan(x) || isnan(y))
return x + y; return x + y;
ux.value = x; if (ux.i == uy.i)
uy.value = y;
if (ux.bits == uy.bits)
return y; return y;
ax = ux.bits & ~SIGN; ax = ux.i & -1ULL/2;
ay = uy.bits & ~SIGN; ay = uy.i & -1ULL/2;
if (ax == 0) { if (ax == 0) {
if (ay == 0) if (ay == 0)
return y; return y;
ux.bits = (uy.bits & SIGN) | 1; ux.i = (uy.i & 1ULL<<63) | 1;
} else if (ax > ay || ((ux.bits ^ uy.bits) & SIGN)) } else if (ax > ay || ((ux.i ^ uy.i) & 1ULL<<63))
ux.bits--; ux.i--;
else else
ux.bits++; ux.i++;
e = ux.bits >> 52 & 0x7ff; e = ux.i >> 52 & 0x7ff;
/* raise overflow if ux.value is infinite and x is finite */ /* raise overflow if ux.f is infinite and x is finite */
if (e == 0x7ff) if (e == 0x7ff)
FORCE_EVAL(x+x); FORCE_EVAL(x+x);
/* raise underflow if ux.value is subnormal or zero */ /* raise underflow if ux.f is subnormal or zero */
if (e == 0) if (e == 0)
FORCE_EVAL(x*x + ux.value*ux.value); FORCE_EVAL(x*x + ux.f*ux.f);
return ux.value; return ux.f;
} }

View File

@ -1,34 +1,30 @@
#include "libm.h" #include "libm.h"
#define SIGN 0x80000000
float nextafterf(float x, float y) float nextafterf(float x, float y)
{ {
union fshape ux, uy; union {float f; uint32_t i;} ux={x}, uy={y};
uint32_t ax, ay, e; uint32_t ax, ay, e;
if (isnan(x) || isnan(y)) if (isnan(x) || isnan(y))
return x + y; return x + y;
ux.value = x; if (ux.i == uy.i)
uy.value = y;
if (ux.bits == uy.bits)
return y; return y;
ax = ux.bits & ~SIGN; ax = ux.i & 0x7fffffff;
ay = uy.bits & ~SIGN; ay = uy.i & 0x7fffffff;
if (ax == 0) { if (ax == 0) {
if (ay == 0) if (ay == 0)
return y; return y;
ux.bits = (uy.bits & SIGN) | 1; ux.i = (uy.i & 0x80000000) | 1;
} else if (ax > ay || ((ux.bits ^ uy.bits) & SIGN)) } else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000))
ux.bits--; ux.i--;
else else
ux.bits++; ux.i++;
e = ux.bits & 0x7f800000; e = ux.i & 0x7f800000;
/* raise overflow if ux.value is infinite and x is finite */ /* raise overflow if ux.f is infinite and x is finite */
if (e == 0x7f800000) if (e == 0x7f800000)
FORCE_EVAL(x+x); FORCE_EVAL(x+x);
/* raise underflow if ux.value is subnormal or zero */ /* raise underflow if ux.f is subnormal or zero */
if (e == 0) if (e == 0)
FORCE_EVAL(x*x + ux.value*ux.value); FORCE_EVAL(x*x + ux.f*ux.f);
return ux.value; return ux.f;
} }

View File

@ -6,40 +6,37 @@ double nexttoward(double x, long double y)
return nextafter(x, y); return nextafter(x, y);
} }
#else #else
#define SIGN ((uint64_t)1<<63)
double nexttoward(double x, long double y) double nexttoward(double x, long double y)
{ {
union dshape ux; union {double f; uint64_t i;} ux = {x};
int e; int e;
if (isnan(x) || isnan(y)) if (isnan(x) || isnan(y))
return x + y; return x + y;
if (x == y) if (x == y)
return y; return y;
ux.value = x;
if (x == 0) { if (x == 0) {
ux.bits = 1; ux.i = 1;
if (signbit(y)) if (signbit(y))
ux.bits |= SIGN; ux.i |= 1ULL<<63;
} else if (x < y) { } else if (x < y) {
if (signbit(x)) if (signbit(x))
ux.bits--; ux.i--;
else else
ux.bits++; ux.i++;
} else { } else {
if (signbit(x)) if (signbit(x))
ux.bits++; ux.i++;
else else
ux.bits--; ux.i--;
} }
e = ux.bits>>52 & 0x7ff; e = ux.i>>52 & 0x7ff;
/* raise overflow if ux.value is infinite and x is finite */ /* raise overflow if ux.f is infinite and x is finite */
if (e == 0x7ff) if (e == 0x7ff)
FORCE_EVAL(x+x); FORCE_EVAL(x+x);
/* raise underflow if ux.value is subnormal or zero */ /* raise underflow if ux.f is subnormal or zero */
if (e == 0) if (e == 0)
FORCE_EVAL(x*x + ux.value*ux.value); FORCE_EVAL(x*x + ux.f*ux.f);
return ux.value; return ux.f;
} }
#endif #endif

View File

@ -2,35 +2,34 @@
float nexttowardf(float x, long double y) float nexttowardf(float x, long double y)
{ {
union fshape ux; union {float f; uint32_t i;} ux = {x};
uint32_t e; uint32_t e;
if (isnan(x) || isnan(y)) if (isnan(x) || isnan(y))
return x + y; return x + y;
if (x == y) if (x == y)
return y; return y;
ux.value = x;
if (x == 0) { if (x == 0) {
ux.bits = 1; ux.i = 1;
if (signbit(y)) if (signbit(y))
ux.bits |= 0x80000000; ux.i |= 0x80000000;
} else if (x < y) { } else if (x < y) {
if (signbit(x)) if (signbit(x))
ux.bits--; ux.i--;
else else
ux.bits++; ux.i++;
} else { } else {
if (signbit(x)) if (signbit(x))
ux.bits++; ux.i++;
else else
ux.bits--; ux.i--;
} }
e = ux.bits & 0x7f800000; e = ux.i & 0x7f800000;
/* raise overflow if ux.value is infinite and x is finite */ /* raise overflow if ux.f is infinite and x is finite */
if (e == 0x7f800000) if (e == 0x7f800000)
FORCE_EVAL(x+x); FORCE_EVAL(x+x);
/* raise underflow if ux.value is subnormal or zero */ /* raise underflow if ux.f is subnormal or zero */
if (e == 0) if (e == 0)
FORCE_EVAL(x*x + ux.value*ux.value); FORCE_EVAL(x*x + ux.f*ux.f);
return ux.value; return ux.f;
} }