/* FloatingPoint.c */
/*****************************************************************************/
/*                                                                           */
/*    System Dependency Library for Building Portable Software               */
/*    Macintosh Version                                                      */
/*    Written by Thomas R. Lawrence, 1993 - 1994.                            */
/*                                                                           */
/*    This file is Public Domain; it may be used for any purpose whatsoever  */
/*    without restriction.                                                   */
/*                                                                           */
/*    This package is distributed in the hope that it will be useful,        */
/*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                   */
/*                                                                           */
/*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
/*                                                                           */
/*****************************************************************************/

#include "MiscInfo.h"
#include "Debug.h"
#include "Audit.h"
#include "Definitions.h"

#if __powerc
	#include <fp.h>
#elif defined(THINK_C)
	#pragma options(pack_enums)
	#include <SANE.h>
	#pragma options(!pack_enums)
#else
	#error "unknown compiler"
#endif

#include "FloatingPoint.h"


#ifdef THINK_C
	#if !__option(mc68881) && __option(native_fp)
		/* native for no FPU = always 10-byte (no convertion necessary) */
		#define x80tox96(X,Y) (*(Y) = *(X))
		#define x96tox80(X,Y) (*(Y) = *(X))
	#else
		/* use normal definition */
	#endif
#else
	#if __powerc
		#define x80tox96(X,Y) (*(Y) = *(X))
		#define x96tox80(X,Y) (*(Y) = *(X))
	#endif
#endif


long double				XGETPI(void)
	{
#if __powerc
		return pi;
#else
		extended			A;
		long double		B;

		A = pi();
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XATAN(long double X)
	{
#if __powerc
		return atan(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = atan(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XCOS(long double X)
	{
#if __powerc
		return cos(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = cos(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XEXP(long double X)
	{
#if __powerc
		return exp(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = exp(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XFABS(long double X)
	{
#if __powerc
		return fabs(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = fabs(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XLN(long double X)
	{
#if __powerc
		return log(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = log(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XSIN(long double X)
	{
#if __powerc
		return sin(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = sin(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XSQRT(long double X)
	{
#if __powerc
		return sqrt(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = sqrt(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XTAN(long double X)
	{
#if __powerc
		return tan(X);
#else
		extended			A;
		long double		B;

		x96tox80(&X,&A);
		A = tan(A);
		x80tox96(&A,&B);
		return B;
#endif
	}


long double				XPOWER(long double X, long double Y)
	{
#if __powerc
		return pow(X,Y);
#else
		extended			XX;
		extended			YY;
		extended			ZZ;
		long double		Z;

		x96tox80(&X,&XX);
		x96tox80(&Y,&YY);
		ZZ = power(XX,YY);
		x80tox96(&ZZ,&Z);
		return Z;
#endif
	}


long double				XACOS(long double X)
	{
#if __powerc
		return acos(X);
#else
		return 2 * XATAN(XSQRT((1 - X) / (1 + X)));
#endif
	}


long double				XASIN(long double X)
	{
#if __powerc
		return asin(X);
#else
		long double		Y;

		Y = XFABS(X);
		if (Y > 0.5)
			{
				Y = 1 - Y;
				Y = 2 * Y - Y * Y;
			}
		 else
			{
				Y = 1 - Y * Y;
			}
		return XATAN(X / XSQRT(Y));
#endif
	}


MyBoolean					ISNAN(long double X)
	{
#if __powerc
		return !isfinite(X);
#else
		extended			XX;
		numclass			Form;

		x96tox80(&X,&XX);
		Form = classextended(XX);
		return ((Form != NORMALNUM) && (Form != ZERONUM) && (Form != DENORMALNUM));
#endif
	}


long double				XCEIL(long double X)
	{
#if __powerc
		return ceil(X);
#else
		rounddir				OldRound;
		extended				S;

		x96tox80(&X,&S);
		OldRound = getround();
		setround(UPWARD);
		S = rint(S);
		setround(OldRound);
		x80tox96(&S,&X);
		return X;
#endif
	}


long double				XFLOOR(long double X)
	{
#if __powerc
		return floor(X);
#else
		rounddir				OldRound;
		extended				S;

		x96tox80(&X,&S);
		OldRound = getround();
		setround(DOWNWARD);
		S = rint(S);
		setround(OldRound);
		x80tox96(&S,&X);
		return X;
#endif
	}
