mirror of
https://github.com/zeux/pugixml.git
synced 2024-12-28 23:03:00 +08:00
Changed fp specials handling in XPath (using fpclassify/fpclass where possible, NaN generation is based on float QNaN, removed magic double constants/byte arrays)
git-svn-id: http://pugixml.googlecode.com/svn/trunk@479 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
a0887a0124
commit
51bb70cdcf
@ -28,6 +28,14 @@
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
// int32_t
|
||||
#if !defined(_MSC_VER) || _MSC_VER >= 1600
|
||||
# include <stdint.h>
|
||||
#else
|
||||
typedef __int32 int32_t;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(disable: 4127) // conditional expression is constant
|
||||
# pragma warning(disable: 4702) // unreachable code
|
||||
@ -261,100 +269,83 @@ namespace
|
||||
}
|
||||
};
|
||||
|
||||
/* From trio
|
||||
*
|
||||
* Endian-agnostic indexing macro.
|
||||
*
|
||||
* The value of internalEndianMagic, when converted into a 64-bit
|
||||
* integer, becomes 0x0706050403020100 (we could have used a 64-bit
|
||||
* integer value instead of a double, but not all platforms supports
|
||||
* that type). The value is automatically encoded with the correct
|
||||
* endianess by the compiler, which means that we can support any
|
||||
* kind of endianess. The individual bytes are then used as an index
|
||||
* for the IEEE 754 bit-patterns and masks.
|
||||
*/
|
||||
#define DOUBLE_INDEX(x) (((unsigned char *)&internal_endian_magic)[7-(x)])
|
||||
|
||||
static const double internal_endian_magic = 7.949928895127363e-275;
|
||||
|
||||
static const unsigned char ieee_754_exponent_mask[] = { 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
static const unsigned char ieee_754_mantissa_mask[] = { 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
|
||||
static const unsigned char ieee_754_qnan_array[] = { 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
bool is_special(double value, bool& has_mantissa)
|
||||
{
|
||||
bool is_special_quantity = true;
|
||||
|
||||
has_mantissa = false;
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(double); ++i)
|
||||
{
|
||||
unsigned char current = ((unsigned char *)&value)[DOUBLE_INDEX(i)];
|
||||
|
||||
is_special_quantity = is_special_quantity && (current & ieee_754_exponent_mask[i]) == ieee_754_exponent_mask[i];
|
||||
has_mantissa = has_mantissa || (current & ieee_754_mantissa_mask[i]) != 0;
|
||||
}
|
||||
|
||||
return is_special_quantity;
|
||||
}
|
||||
|
||||
double gen_nan()
|
||||
{
|
||||
#if FLT_RADIX == 2 && DBL_MAX_EXP == 1024 && DBL_MANT_DIG == 53
|
||||
// IEEE 754
|
||||
|
||||
double result = 0;
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(double); ++i)
|
||||
{
|
||||
((unsigned char *)&result)[DOUBLE_INDEX(i)] = ieee_754_qnan_array[i];
|
||||
}
|
||||
|
||||
return result;
|
||||
#else
|
||||
#if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24))
|
||||
union { float f; int32_t i; } u[sizeof(float) == sizeof(int32_t) ? 1 : -1];
|
||||
u[0].i = 0x7fc00000;
|
||||
return u[0].f;
|
||||
#else
|
||||
// fallback
|
||||
const volatile double zero = 0.0;
|
||||
return zero / zero;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_nan(double value)
|
||||
{
|
||||
#if defined(__USE_ISOC99)
|
||||
return isnan(value);
|
||||
#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__COMO__)
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
return !!_isnan(value);
|
||||
#elif FLT_RADIX == 2 && DBL_MAX_EXP == 1024 && DBL_MANT_DIG == 53
|
||||
// IEEE 754
|
||||
|
||||
bool has_mantissa;
|
||||
|
||||
bool is_special_quantity = is_special(value, has_mantissa);
|
||||
|
||||
return (is_special_quantity && has_mantissa);
|
||||
#else
|
||||
return value != value;
|
||||
#endif
|
||||
#elif defined(FP_NAN)
|
||||
return fpclassify(value) == FP_NAN;
|
||||
#else
|
||||
// fallback
|
||||
const volatile double v = value;
|
||||
return v != v;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_inf(double value)
|
||||
const char_t* convert_number_to_string_special(double value)
|
||||
{
|
||||
#if defined(__USE_ISOC99)
|
||||
return !isfinite(value);
|
||||
#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && !defined(__COMO__)
|
||||
return !_finite(value);
|
||||
#elif FLT_RADIX == 2 && DBL_MAX_EXP == 1024 && DBL_MANT_DIG == 53
|
||||
// IEEE 754
|
||||
|
||||
bool has_mantissa;
|
||||
|
||||
bool is_special_quantity = is_special(value, has_mantissa);
|
||||
|
||||
return (is_special_quantity && !has_mantissa);
|
||||
#else
|
||||
return value + 1 == value && value - 1 == value;
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
switch (_fpclass(value))
|
||||
{
|
||||
case _FPCLASS_SNAN:
|
||||
case _FPCLASS_QNAN:
|
||||
return PUGIXML_TEXT("NaN");
|
||||
|
||||
case _FPCLASS_NINF:
|
||||
return PUGIXML_TEXT("-Infinity");
|
||||
|
||||
case _FPCLASS_NZ:
|
||||
case _FPCLASS_PZ:
|
||||
return PUGIXML_TEXT("0");
|
||||
|
||||
case _FPCLASS_PINF:
|
||||
return PUGIXML_TEXT("Infinity");
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#elif defined(__BORLANDC__) // _fpclass in BorlandC breaks fp flags
|
||||
if (_isnan(value)) return PUGIXML_TEXT("NaN");
|
||||
if (!_finite(value)) return PUGIXML_TEXT("-Infinity") + (value > 0);
|
||||
if (value == 0) return PUGIXML_TEXT("0");
|
||||
return 0;
|
||||
#elif defined(FP_NAN) && defined(FP_INFINITE) && defined(FP_ZERO)
|
||||
switch (fpclassify(value))
|
||||
{
|
||||
case FP_NAN:
|
||||
return PUGIXML_TEXT("NaN");
|
||||
|
||||
case FP_INFINITE:
|
||||
return PUGIXML_TEXT("-Infinity") + (value > 0);
|
||||
|
||||
case FP_ZERO:
|
||||
return PUGIXML_TEXT("0");
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
// fallback
|
||||
const volatile double v = value;
|
||||
|
||||
if (v == 0) return PUGIXML_TEXT("0");
|
||||
if (v != v) return PUGIXML_TEXT("NaN");
|
||||
if (v * 2 == v) return PUGIXML_TEXT("-Infinity") + (value > 0);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool convert_number_to_boolean(double value)
|
||||
@ -364,9 +355,8 @@ namespace
|
||||
|
||||
string_t convert_number_to_string(double value)
|
||||
{
|
||||
if (is_nan(value)) return PUGIXML_TEXT("NaN");
|
||||
else if (is_inf(value)) return value < 0 ? PUGIXML_TEXT("-Infinity") : PUGIXML_TEXT("Infinity");
|
||||
else if (value == 0) return PUGIXML_TEXT("0");
|
||||
const char_t* special = convert_number_to_string_special(value);
|
||||
if (special) return special;
|
||||
|
||||
char buf[512];
|
||||
sprintf(buf, "%f", value);
|
||||
|
Loading…
x
Reference in New Issue
Block a user