summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorarseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640>2010-05-31 07:41:54 +0000
committerarseny.kapoulkine <arseny.kapoulkine@99668b35-9821-0410-8761-19e4c4f06640>2010-05-31 07:41:54 +0000
commit51bb70cdcf772093c97655b65ab1691c6025e0b5 (patch)
tree7d8131f2813cac838ba1acf96b40bdb368eed542
parenta0887a0124e35c7a35202132f108b1da5590d075 (diff)
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
-rw-r--r--src/pugixpath.cpp162
1 files changed, 76 insertions, 86 deletions
diff --git a/src/pugixpath.cpp b/src/pugixpath.cpp
index a22943b..f0d3706 100644
--- a/src/pugixpath.cpp
+++ b/src/pugixpath.cpp
@@ -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)
- {
-#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
+ const char_t* convert_number_to_string_special(double value)
+ {
+ #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);