blob: 69086daf88bbdafedaa84bf9e16461276c092104 [file] [log] [blame]
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
double frexp(double value, int* exp);
#if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) || \
defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__)
#include <stdint.h>
/* It is assumed that `double` conforms to IEEE 754 and is little-endian.
* This is true on x86 and ARM. */
typedef union ieee754_double_ {
struct __attribute__((__packed__)) {
uint64_t f52 : 52;
uint64_t exp : 11;
uint64_t sgn : 1;
};
double f;
} ieee754_double;
double frexp(double value, int* exp)
{
int n;
ieee754_double reg;
reg.f = value;
if(reg.exp == 0x7FF) {
/* The value is an infinity or NaN.
* Store zero in `*exp`. Return the value as is. */
*exp = 0;
return reg.f;
}
if(reg.exp != 0) {
/* The value is normalized.
* Extract and zero out the exponent. */
*exp = reg.exp - 0x3FE;
reg.exp = 0x3FE;
return reg.f;
}
if(reg.f52 == 0) {
/* The value is zero.
* Store zero in `*exp`. Return the value as is.
* Note the signness. */
*exp = 0;
return reg.f;
}
/* The value is denormalized.
* Extract the exponent, normalize the value, then zero out
* the exponent. Note that the hidden bit is removed. */
n = __builtin_clzll(reg.f52) - 11;
reg.f52 <<= n;
*exp = 1 - 0x3FE - n;
reg.exp = 0x3FE;
return reg.f;
}
#else
#error Please add `frexp()` implementation for this platform.
#endif