64 lines
1.5 KiB
C++
64 lines
1.5 KiB
C++
/*
|
|
* Copyright (c) 2017 Andrew Kelley
|
|
*
|
|
* This file is part of zig, which is MIT licensed.
|
|
* See http://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#ifndef ZIG_SOFTFLOAT_HPP
|
|
#define ZIG_SOFTFLOAT_HPP
|
|
|
|
extern "C" {
|
|
#include "softfloat.h"
|
|
}
|
|
|
|
#include "zigendian.h"
|
|
|
|
static inline float16_t zig_double_to_f16(double x) {
|
|
float64_t y;
|
|
static_assert(sizeof(x) == sizeof(y), "");
|
|
memcpy(&y, &x, sizeof(x));
|
|
return f64_to_f16(y);
|
|
}
|
|
|
|
|
|
// Return value is safe to coerce to float even when |x| is NaN or Infinity.
|
|
static inline double zig_f16_to_double(float16_t x) {
|
|
float64_t y = f16_to_f64(x);
|
|
double z;
|
|
static_assert(sizeof(y) == sizeof(z), "");
|
|
memcpy(&z, &y, sizeof(y));
|
|
return z;
|
|
}
|
|
|
|
static inline bool zig_f16_isNaN(float16_t a) {
|
|
union { uint16_t ui; float16_t f; } uA;
|
|
uA.f = a;
|
|
return 0x7C00 < (uA.ui & 0x7FFF);
|
|
}
|
|
|
|
static inline bool zig_f128_isNaN(float128_t *aPtr) {
|
|
uint64_t hi, lo;
|
|
|
|
#if defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_LITTLE_ENDIAN
|
|
hi = aPtr->v[1];
|
|
lo = aPtr->v[0];
|
|
#elif defined(ZIG_BYTE_ORDER) && ZIG_BYTE_ORDER == ZIG_BIG_ENDIAN
|
|
hi = aPtr->v[0];
|
|
lo = aPtr->v[1];
|
|
#else
|
|
#error Unsupported endian
|
|
#endif
|
|
|
|
uint64_t absA64 = hi & UINT64_C(0x7FFFFFFFFFFFFFFF);
|
|
return
|
|
(UINT64_C(0x7FFF000000000000) < absA64)
|
|
|| ((absA64 == UINT64_C(0x7FFF000000000000)) && lo);
|
|
}
|
|
|
|
static inline bool zig_extF80_isNaN(extFloat80_t *aPtr) {
|
|
return (aPtr->signExp & 0x7FFF) == 0x7FFF && aPtr->signif & UINT64_C(0x7FFFFFFFFFFFFFFF);
|
|
}
|
|
|
|
#endif
|