|  | /** | 
|  | * 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. | 
|  | */ | 
|  | long double frexpl(long double value, int* exp); | 
|  |  | 
|  | #if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) | 
|  |  | 
|  | double frexp(double value, int* exp); | 
|  |  | 
|  | /* On ARM `long double` is 64 bits. */ | 
|  | long double frexpl(long double value, int* exp) | 
|  | { | 
|  | return frexp(value, exp); | 
|  | } | 
|  |  | 
|  | #elif defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) | 
|  |  | 
|  | #include <stdint.h> | 
|  |  | 
|  | /* https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format */ | 
|  | typedef union x87reg_ { | 
|  | struct __attribute__((__packed__)) { | 
|  | uint64_t f64; | 
|  | uint16_t exp : 15; | 
|  | uint16_t sgn :  1; | 
|  | }; | 
|  | long double f; | 
|  | } x87reg; | 
|  |  | 
|  | long double frexpl(long double value, int* exp) | 
|  | { | 
|  | int n; | 
|  | x87reg reg; | 
|  | reg.f = value; | 
|  | if(reg.exp == 0x7FFF) { | 
|  | /* 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 - 0x3FFE; | 
|  | reg.exp = 0x3FFE; | 
|  | return reg.f; | 
|  | } | 
|  | if(reg.f64 == 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 x87 uses an explicit leading bit. */ | 
|  | n = __builtin_clzll(reg.f64); | 
|  | reg.f64 <<= n; | 
|  | *exp = 1 - 0x3FFE - n; | 
|  | reg.exp = 0x3FFE; | 
|  | return reg.f; | 
|  | } | 
|  |  | 
|  | #else | 
|  |  | 
|  | #error Please add `frexpl()` implementation for this platform. | 
|  |  | 
|  | #endif |