frexp: handle NaN values (from sources)

This commit is contained in:
cinap_lenrek 2013-05-01 16:44:04 +02:00
parent 27f65a138a
commit decade55c6
2 changed files with 23 additions and 11 deletions

View file

@ -6,6 +6,7 @@
#define MASK 0x7ffL #define MASK 0x7ffL
#define SHIFT 20 #define SHIFT 20
#define BIAS 1022L #define BIAS 1022L
#define SIG 52
typedef union typedef union
{ {
@ -25,13 +26,18 @@ typedef union
double double
frexp(double d, int *ep) frexp(double d, int *ep)
{ {
Cheat x; Cheat x, a;
if(d == 0) { *ep = 0;
*ep = 0; /* order matters: only isNaN can operate on NaN */
return 0; if(isNaN(d) || isInf(d, 0) || d == 0)
} return d;
x.d = d; x.d = d;
a.d = fabs(d);
if((a.ms >> SHIFT) == 0){ /* normalize subnormal numbers */
x.d = (double)(1ULL<<SIG) * d;
*ep = -SIG;
}
*ep = ((x.ms >> SHIFT) & MASK) - BIAS; *ep = ((x.ms >> SHIFT) & MASK) - BIAS;
x.ms &= ~(MASK << SHIFT); x.ms &= ~(MASK << SHIFT);
x.ms |= BIAS << SHIFT; x.ms |= BIAS << SHIFT;

View file

@ -9,18 +9,24 @@
#define MASK 0x7ffL #define MASK 0x7ffL
#define SHIFT 20 #define SHIFT 20
#define BIAS 1022L #define BIAS 1022L
#define SIG 52
double double
frexp(double d, int *ep) frexp(double d, int *ep)
{ {
FPdbleword x; FPdbleword x, a;
if(d == 0) { *ep = 0;
*ep = 0; /* order matters: only isNaN can operate on NaN */
return 0; if(isNaN(d) || isInf(d, 0) || d == 0)
} return d;
x.x = d; x.x = d;
*ep = ((x.hi >> SHIFT) & MASK) - BIAS; a.x = fabs(d);
if((a.hi >> SHIFT) == 0){ /* normalize subnormal numbers */
x.x = (double)(1ULL<<SIG) * d;
*ep = -SIG;
}
*ep += ((x.hi >> SHIFT) & MASK) - BIAS;
x.hi &= ~(MASK << SHIFT); x.hi &= ~(MASK << SHIFT);
x.hi |= BIAS << SHIFT; x.hi |= BIAS << SHIFT;
return x.x; return x.x;