#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)!
#ifdef __GNUC__
#undef	isnan
#undef	isinfinite

Bool isnan( Real f )
{
	ULONG exp, mant;

	mant = exp = *((ULONG *)&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( LReal d )
{
	LULONG exp, mant;

	mant = exp = *((LULONG *)&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( Real f )
{
	ULONG exp, mant;

	mant = exp = *((ULONG *)&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( LReal d )
{
	LULONG exp, mant;

	mant = exp = *((LULONG *)&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 __MAC
	#include "float.h"
#endif

Real RepairFloat(Real r)
{
#ifdef __PC
	if (_isnan(r) || !_finite(r))
		return 0.0;
#else
	if (isnan(r) || !isfinite(r))
		return 0.0;
#endif
	return r;
}

LReal RepairFloat(LReal r)
{
#ifdef __PC
	if (_isnan(r) || !_finite(r))
		return 0.0;
#else
	if (isnan(r) || !isfinite(r))
		return 0.0;
#endif
	return r;
}

Bool CompareFloatTolerant(Real a, Real b)
{
	LONG *va = (LONG*) & a;
	LONG *vb = (LONG*) & b;

	return Abs(*va - *vb) <= 7;
}
