Files
zig/src/stage1/softfloat.hpp
Koakuma 09450419d3 Fix f128 NaN check on big-endian hosts
On big-endian hosts, zig_f128_isNaN() takes the high and low halves
from the wrong element, resulting in buggy NaN detection behavior.
This fixes it.
2021-01-25 10:40:23 -08:00

60 lines
1.4 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);
}
#endif