mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-28 23:49:26 +00:00
clean up fpinfo a little bit.
This commit is contained in:
parent
728de4ddaa
commit
9d302c5dcc
@ -21,7 +21,7 @@
|
||||
#define bswap32 __builtin_bswap32
|
||||
#define bswap64 __builtin_bswap64
|
||||
|
||||
#if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
#define htobe16(x) bswap16((x))
|
||||
#define htobe32(x) bswap32((x))
|
||||
#define htobe64(x) bswap64((x))
|
||||
@ -35,7 +35,7 @@
|
||||
#define le16toh(x) ((uint16_t)(x))
|
||||
#define le32toh(x) ((uint32_t)(x))
|
||||
#define le64toh(x) ((uint64_t)(x))
|
||||
#else /* _BYTE_ORDER != _LITTLE_ENDIAN */
|
||||
#else /* BYTE_ORDER != LITTLE_ENDIAN */
|
||||
#define htobe16(x) ((uint16_t)(x))
|
||||
#define htobe32(x) ((uint32_t)(x))
|
||||
#define htobe64(x) ((uint64_t)(x))
|
||||
@ -49,7 +49,28 @@
|
||||
#define le16toh(x) bswap16((x))
|
||||
#define le32toh(x) bswap32((x))
|
||||
#define le64toh(x) bswap64((x))
|
||||
#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */
|
||||
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
// https://github.com/HowardHinnant/hash_append/blob/master/endian.h
|
||||
enum class endian
|
||||
{
|
||||
native = LITTLE_ENDIAN,
|
||||
little = LITTLE_ENDIAN,
|
||||
big = BIG_ENDIAN
|
||||
};
|
||||
|
||||
static_assert(endian::native == endian::little ||
|
||||
endian::native == endian::big,
|
||||
"endian::native shall be one of endian::little or endian::big");
|
||||
|
||||
static_assert(endian::big != endian::little,
|
||||
"endian::big and endian::little shall have different values");
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -7,6 +7,154 @@ static_assert(sizeof(float) == 4, "Unexpected float size");
|
||||
static_assert(sizeof(double) == 8, "Unexpected double size");
|
||||
static_assert(sizeof(long double) == 8 || sizeof(long double) == 12 || sizeof(long double) == 16, "Unexpected long double size");
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
template<int size>
|
||||
void init(const void *vp, fpinfo &info);
|
||||
|
||||
// 32-bit float
|
||||
template<>
|
||||
void init<4>(const void *vp, fpinfo &info) {
|
||||
|
||||
|
||||
uint32_t i = *(uint32_t *)vp;
|
||||
|
||||
info.sign = i >> 31;
|
||||
info.one = 1;
|
||||
info.exp = (i >> 23) & ((1 << 8) - 1);
|
||||
info.sig = i & ((1 << 24) - 1);
|
||||
|
||||
if (info.exp == 255) {
|
||||
if (info.sig == 0) info.inf = true;
|
||||
else info.nan = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.exp == 0) {
|
||||
// 0 or denormalized.
|
||||
info.one = 0;
|
||||
info.exp = -126;
|
||||
return;
|
||||
}
|
||||
|
||||
info.exp -= 127; // bias
|
||||
}
|
||||
|
||||
// 64-bit double or long double.
|
||||
template<>
|
||||
void init<8>(const void *vp, fpinfo &info) {
|
||||
|
||||
uint64_t i = *(uint64_t *)vp;
|
||||
|
||||
info.sign = i >> 63;
|
||||
info.one = 1;
|
||||
info.exp = (i >> 52) & ((1 << 11) - 1);
|
||||
info.sig = i & ((UINT64_C(1) << 53) - 1);
|
||||
|
||||
|
||||
if (info.exp == 2047) {
|
||||
if (info.sig == 0) info.inf = true;
|
||||
else info.nan = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.exp == 0) {
|
||||
// 0 or denormalized.
|
||||
info.one = 0;
|
||||
info.exp = -1022;
|
||||
return;
|
||||
}
|
||||
|
||||
info.exp -= 1023; // bias
|
||||
}
|
||||
|
||||
/* solaris - 96-bit long double. */
|
||||
template<>
|
||||
void init<12>(const void *vp, fpinfo &info) {
|
||||
|
||||
|
||||
uint64_t i;
|
||||
uint32_t sexp;
|
||||
|
||||
|
||||
// this needs to be verified.
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
i = ((uint64_t *)vp)[0];
|
||||
sexp = ((uint32_t *)vp)[2] & 0xffff;
|
||||
#else
|
||||
#error "please verify big-endian long double format."
|
||||
sexp = *((uint32_t *)vp) & 0xffff;
|
||||
i = *((uint64_t *)((uint8_t *)vp+4);
|
||||
#endif
|
||||
|
||||
info.sign = (sexp >> 15) & 0x01;
|
||||
info.exp = sexp & ((1 << 15) - 1);
|
||||
|
||||
info.one = i >> 63;
|
||||
info.sig = i & ((UINT64_C(1) << 63) - 1);
|
||||
|
||||
if (info.exp == 32767) {
|
||||
if (info.sig == 0) info.inf = true;
|
||||
else info.nan = true;
|
||||
return;
|
||||
}
|
||||
//
|
||||
|
||||
info.exp -= 16383;
|
||||
|
||||
}
|
||||
|
||||
/* 128-bit long double. same format as 96 but extra padding */
|
||||
template<>
|
||||
void init<16>(const void *vp, fpinfo &info) {
|
||||
|
||||
uint64_t i;
|
||||
uint32_t sexp;
|
||||
|
||||
|
||||
// this needs to be verified.
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
i = ((uint64_t *)vp)[0];
|
||||
sexp = ((uint32_t *)vp)[2] & 0xffff;
|
||||
#else
|
||||
#error "please verify big-endian long double format."
|
||||
i = ((uint64_t *)vp)[1];
|
||||
sexp = ((uint64_t *)vp)[0] & 0xffff;
|
||||
#endif
|
||||
|
||||
info.sign = (sexp >> 15) & 0x01;
|
||||
info.exp = sexp & ((1 << 15) - 1);
|
||||
|
||||
info.one = i >> 63;
|
||||
info.sig = i & ((UINT64_C(1) << 63) - 1);
|
||||
|
||||
if (info.exp == 32767) {
|
||||
if (info.sig == 0) info.inf = true;
|
||||
else info.nan = true;
|
||||
return;
|
||||
}
|
||||
//
|
||||
|
||||
info.exp -= 16383;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fpinfo::fpinfo(const float &f) {
|
||||
init<sizeof(f)>(&f, *this);
|
||||
}
|
||||
fpinfo::fpinfo(const double &d) {
|
||||
init<sizeof(d)>(&d, *this);
|
||||
|
||||
}
|
||||
fpinfo::fpinfo(const long double &ld) {
|
||||
init<sizeof(ld)>(&ld, *this);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void fpinfo::init(float *f)
|
||||
{
|
||||
union split {
|
||||
@ -104,3 +252,5 @@ void fpinfo::init(long double *ld)
|
||||
|
||||
exp -= 16383;
|
||||
}
|
||||
|
||||
#endif
|
@ -4,6 +4,16 @@
|
||||
#include <cstdint>
|
||||
|
||||
struct fpinfo {
|
||||
|
||||
private:
|
||||
/*
|
||||
void init(float *);
|
||||
void init(double *);
|
||||
void init(long double *);
|
||||
*/
|
||||
|
||||
public:
|
||||
|
||||
bool sign = false;
|
||||
bool one = false;
|
||||
int exp = 0;
|
||||
@ -12,17 +22,9 @@ struct fpinfo {
|
||||
bool nan = false;
|
||||
bool inf = false;
|
||||
|
||||
fpinfo(float f) { init(&f); }
|
||||
fpinfo(double d) { init(&d); }
|
||||
fpinfo(long double ld) {
|
||||
if (sizeof(long double) == 16 || sizeof(long double) == 12) init(&ld);
|
||||
if (sizeof(long double) == 8) init((double *)&ld);
|
||||
}
|
||||
|
||||
private:
|
||||
void init(float *);
|
||||
void init(double *);
|
||||
void init(long double *);
|
||||
fpinfo(const float &f);
|
||||
fpinfo(const double &d);
|
||||
fpinfo(const long double &ld);
|
||||
};
|
||||
|
||||
|
||||
|
@ -167,7 +167,7 @@ using its_complicated::signbit;
|
||||
template<>
|
||||
long double readnum<long double>(uint32_t address)
|
||||
{
|
||||
char buffer[16];
|
||||
uint8_t buffer[16];
|
||||
|
||||
static_assert(sizeof(long double) == 16 || sizeof(long double) == 12, "unexpected long double size");
|
||||
|
||||
@ -237,7 +237,7 @@ using its_complicated::signbit;
|
||||
{
|
||||
static_assert(sizeof(value) == 16 || sizeof(value) == 12, "unexpected long double size");
|
||||
|
||||
char buffer[16];
|
||||
uint8_t buffer[16];
|
||||
|
||||
std::memcpy(buffer, &value, sizeof(value));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user