|  | /** | 
|  | * 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 |