Browse Source

Merge pull request #11409 from MarufSarker/PR-core-math-is_nan

Verbose and Platform-specific implementation for is_nan
Rémi Verschelde 8 years ago
parent
commit
e3617cb187
1 changed files with 38 additions and 2 deletions
  1. 38 2
      core/math/math_funcs.h

+ 38 - 2
core/math/math_funcs.h

@@ -104,8 +104,44 @@ public:
 	static _ALWAYS_INLINE_ double exp(double p_x) { return ::exp(p_x); }
 	static _ALWAYS_INLINE_ float exp(float p_x) { return ::expf(p_x); }
 
-	static _ALWAYS_INLINE_ bool is_nan(double p_val) { return (p_val != p_val); }
-	static _ALWAYS_INLINE_ bool is_nan(float p_val) { return (p_val != p_val); }
+	static _ALWAYS_INLINE_ bool is_nan(double p_val) {
+#ifdef _MSC_VER
+		return _isnan(p_val);
+#elif defined(__GNUC__) && __GNUC__ < 6
+		union {
+			uint64_t u;
+			double f;
+		} ieee754;
+		ieee754.f = p_val;
+		// (unsigned)(0x7ff0000000000001 >> 32) : 0x7ff00000
+		return ((((unsigned)(ieee754.u >> 32) & 0x7fffffff) + ((unsigned)ieee754.u != 0)) > 0x7ff00000);
+#else
+		return isnan(p_val);
+#endif
+	}
+
+	static _ALWAYS_INLINE_ bool is_nan(float p_val) {
+#ifdef _MSC_VER
+		return _isnan(p_val);
+#elif defined(__GNUC__) && __GNUC__ < 6
+		union {
+			uint32_t u;
+			float f;
+		} ieee754;
+		ieee754.f = p_val;
+		// -----------------------------------
+		// (single-precision floating-point)
+		// NaN : s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx
+		//     : (> 0x7f800000)
+		// where,
+		//   s : sign
+		//   x : non-zero number
+		// -----------------------------------
+		return ((ieee754.u & 0x7fffffff) > 0x7f800000);
+#else
+		return isnan(p_val);
+#endif
+	}
 
 	static _ALWAYS_INLINE_ bool is_inf(double p_val) {
 #ifdef _MSC_VER