#include "ge_math.h"

// Bug #6516
// Due to a bug in the gcc compiler when compiling release code and using the Relax IEEE option and fast code optimization,
// the recognition of NaN and INF doesn't work (should be fixed in gcc 4.2 - to be tested).
// Attention: isnan/infinite is only replaced in the context of this source file (when using gcc)!
//
// IDEA #31877: NaN and INF Bug is fixed in gcc 4.2 and therefore the workaround is only applied to older gcc 4.x versions
#if ((__GNUC__ == 4) && (__GNUC_MINOR__ < 2))
#undef	isnan
#undef	isinfinite

Bool isnan(Float32 f)
{
	UInt32 exp, mant;

	mant	= exp = *((UInt32*)&f);
	exp	 &= 0x7f800000L;							// ieee 754 float has 1 sign bit + 8 bits for exponent
	mant &= 0x007fffffL;							// and 23 bits for the mantissa;
	if ((exp == 0x7f800000L) && mant)	// NaN?: all exponent bits set (sign doesn't matter) + mant != 0
		return true;
	else
		return false;
}

Bool isnan(Float64 d)
{
	UInt64 exp, mant;

	mant	= exp = *((UInt64*)&d);
	exp	 &= 0x7ff0000000000000LL;								// ieee 754 double has 1 sign bit + 11 bits for exponent
	mant &= 0x000fffffffffffffLL;								// and 52 bits for the mantissa;

	if ((exp == 0x7ff0000000000000LL) && mant)	// NaN?: all exponent bits set (sign doesn't matter) + mant != 0
		return true;
	else
		return false;
}


Bool isinfinite(Float32 f)
{
	UInt32 exp, mant;

	mant	= exp = *((UInt32*)&f);
	exp	 &= 0x7f800000L;											// ieee 754 float has 1 sign bit + 8 bits for exponent
	mant &= 0x007fffffL;											// and 23 bits for the mantissa;

	if ((exp == 0x7f800000L) && (mant == 0))	// INF?: all exponent bits set (sign doesn't matter) + mant == 0
		return true;
	else
		return false;
}

Bool isinfinite(Float64 d)
{
	UInt64 exp, mant;

	mant	= exp = *((UInt64*)&d);
	exp	 &= 0x7ff0000000000000LL;											// ieee 754 double has 1 sign bit + 11 bits for exponent
	mant &= 0x000fffffffffffffLL;											// and 52 bits for the mantissa;

	if ((exp == 0x7ff0000000000000LL) && (mant == 0))	// INF?: all exponent bits set (sign doesn't matter) + mant == 0
		return true;
	else
		return false;
}
#endif	//__GNUC__

#if defined __PC || defined __LINUX
	#include "float.h"
#else
	#include "ge_math.h"
#endif

Bool CompareFloatTolerant(Float32 a, Float32 b)
{
	Int32* va = (Int32*) &a;
	Int32* vb = (Int32*) &b;

	// UInt32 is necessary because -x-x is 0x80000000 where abs(0x80000000 is illegal)
	return UInt32(Abs(*va - *vb)) <= 7;
}

Bool CompareFloatTolerant(Float64 a, Float64 b)
{
	Int64* va = (Int64*) &a;
	Int64* vb = (Int64*) &b;

	// UInt32 is necessary because -x-x is 0x80000000 where abs(0x80000000 is illegal)
	return UInt64(Abs(*va - *vb)) <= 7;
}
