1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
#include "platform.h"
#if defined (HAS_FPCLASSIFY) && HAS_FPCLASSIFY
C_Int_t Real32_class (Real32_t f) {
return fpclassify (f);
}
#elif defined (HAS_FPCLASSIFY32) && HAS_FPCLASSIFY32
C_Int_t Real32_class (Real32_t f) {
return fpclassify32 (f);
}
#else
/* This code assumes IEEE 754/854.
*
* In little-endian memory, the 32 bits of a float are layed out as follows.
*
* d[0] bits 7-0 of mantissa
* d[1] bits 15-8 of mantissa
* d[2] bit 0 of exponent
* bits 22-16 of mantissa
* d[3] sign bit
* bits 7-1 of exponent
*
* In big-endian memory, the 32 bits of a float are layed out as follows.
*
* d[3] bits 7-0 of mantissa
* d[2] bits 15-8 of mantissa
* d[1] bit 0 of exponent
* bits 22-16 of mantissa
* d[0] sign bit
* bits 7-1 of exponent
*/
/* masks for least/most significant word */
#define EXPONENT_MASK32 0x7F800000
#define MANTISSA_MASK32 0x007FFFFF
#define SIGNBIT_MASK32 0x80000000
#define MANTISSA_HIGHBIT_MASK32 0x00400000
C_Int_t Real32_class (Real32_t f) {
uint32_t word0;
int res;
/* Using memcpy;
* Technically correct.
*/
uint32_t words[1];
memcpy(&words, &f, sizeof(Real32_t));
word0 = words[0];
/* Using union;
* Technically undefined, but widely supported.
*/
/*
union {float f; uint32_t words[1];} fws;
fws.f = f;
word0 = fws.words[0];
*/
if ((word0 & EXPONENT_MASK32) == EXPONENT_MASK32) {
if (word0 & MANTISSA_MASK32)
res = FP_NAN;
else
res = FP_INFINITE;
} else if (word0 & EXPONENT_MASK32)
res = FP_NORMAL;
else if (word0 & MANTISSA_MASK32)
res = FP_SUBNORMAL;
else
res = FP_ZERO;
return res;
}
#endif
#if defined (HAS_FPCLASSIFY) && HAS_FPCLASSIFY
C_Int_t Real64_class (Real64_t d) {
return fpclassify (d);
}
#elif defined (HAS_FPCLASSIFY64) && HAS_FPCLASSIFY64
C_Int_t Real64_class (Real64_t d) {
return fpclassify64 (d);
}
#else
/* This code assumes IEEE 754/854.
*
* In little-endian memory, the 64 bits of a double are layed out as follows.
*
* d[0] bits 7-0 of mantissa
* d[1] bits 15-8 of mantissa
* d[2] bits 23-16 of mantissa
* d[3] bits 31-24 of mantissa
* d[4] bits 39-32 of mantissa
* d[5] bits 47-40 of mantissa
* d[6] bits 3-0 of exponent
* bits 51-48 of mantissa
* d[7] sign bit
* bits 10-4 of exponent
*
* In big-endian memory, the 64 bits of a double are layed out as follows.
*
* d[7] bits 7-0 of mantissa
* d[6] bits 15-8 of mantissa
* d[5] bits 23-16 of mantissa
* d[4] bits 31-24 of mantissa
* d[3] bits 39-32 of mantissa
* d[2] bits 47-40 of mantissa
* d[1] bits 3-0 of exponent
* bits 51-48 of mantissa
* d[0] sign bit
* bits 10-4 of exponent
*/
/* masks for most-significant word */
#define EXPONENT_MASK64 0x7FF00000
#define MANTISSA_MASK64 0x000FFFFF
#define SIGNBIT_MASK64 0x80000000
#define MANTISSA_HIGHBIT_MASK64 0x00080000
C_Int_t Real64_class (Real64_t d) {
uint32_t word0, word1;
int res;
/* Using memcpy;
* Technically correct.
*/
uint32_t words[2];
memcpy(&words, &d, sizeof(Real64_t));
if (isBigEndian()) {
word1 = words[0];
word0 = words[1];
} else {
word0 = words[0];
word1 = words[1];
}
/* Using union;
* Technically undefined, but widely supported.
*/
/*
union {double d; uint32_t words[2];} dws;
dws.d = d;
if (isBigEndian()) {
word1 = dws.words[0];
word0 = dws.words[1];
} else {
word0 = dws.words[0];
word1 = dws.words[1];
}
*/
if ((word1 & EXPONENT_MASK64) == EXPONENT_MASK64) {
if (word0 or (word1 & MANTISSA_MASK64))
res = FP_NAN;
else
res = FP_INFINITE;
} else if (word1 & EXPONENT_MASK64)
res = FP_NORMAL;
else if (word0 or (word1 & MANTISSA_MASK64))
res = FP_SUBNORMAL;
else
res = FP_ZERO;
return res;
}
#endif
|