//	Zinc Application Framework - Z_FILE1.CPP
//	COPYRIGHT (C) 1990-1999.  All Rights Reserved.
//	Zinc Software Incorporated.  Pleasant Grove, Utah  USA

#include <math.h>
#include <z_file.hpp>

union DoubleConvertUnion
{
	double real;
	ZafUInt32 hex[2];
};

int ZafFile::Read(double &value)
{
	int returnValue;
	ZafUInt32 hexValue1, hexValue2;
#if defined(IEEE) || defined (_IEEE)
	DoubleConvertUnion convert;
#	if defined(ZAF_LITTLEENDIAN)
	// Read number highest word first.
	returnValue = Read(hexValue2);
	returnValue += Read(hexValue1);
#	else
	// Use the Read method for longs to take into account byte swapping for
	// big endian machines.
	returnValue = Read(hexValue1);
	returnValue += Read(hexValue2);
#	endif

	convert.hex[0] = hexValue1;
	convert.hex[1] = hexValue2;
	value = (double)convert.real;
#else

	// Convert the value from IEEE to the local format.
	// Use the Read method for longs to take into account byte swapping for
	// big endian machines.
	// Read in the highest bit word first.
	returnValue = Read(hexValue1);
	returnValue += Read(hexValue2);

	if (((hexValue1 & 0x7fffffffL) == 0) && (hexValue2 == 0))
		value = 0;
	else
	{
		bool sign = (hexValue1 & 0x80000000L) ? true : false;
		int exponent = (int)(((hexValue1 & 0x7ff00000L) >> 20) - 1023);
		ZafUInt32 mantissa;
		{
			// The first bit of the mantissa is assumed.
			value = 1.0;
			double tempDouble = 1.0;

			mantissa = (hexValue1 & 0x000fffffL) << 12;
			for (; mantissa; mantissa = mantissa << 1)
			{
				tempDouble /= 2.0;
				if (mantissa & 0x80000000L)
					value += tempDouble;
			}

			mantissa = hexValue2;
			for (; mantissa; mantissa = mantissa << 1)
			{
				tempDouble /= 2.0;
				if (mantissa & 0x80000000L)
					value += tempDouble;
			}
			double doubleExponent = exponent;
			value *= ((sign) ? -1.0 : 1.0) * pow(2.0, doubleExponent);
		}
	}
#endif
	return (returnValue);
}

int ZafFile::Write(double value)
{
	DoubleConvertUnion convert;
	int returnValue;
#if defined(IEEE) || defined(_IEEE)
	convert.real = value;

	// Write as a pair of ZafUInt32 to take care of byte swapping.
#	if defined(ZAF_LITTLEENDIAN)
	// Write the highest word first.
	returnValue = Write(convert.hex[1]);
	returnValue += Write(convert.hex[0]);
#	else
	returnValue = Write(convert.hex[0]);
	returnValue += Write(convert.hex[1]);
#	endif

#else
	convert.hex[0] = 0;
	convert.hex[1] = 0;

	// Convert value to IEEE format before storing it.
	if (value == 0)
	{
		returnValue = Write((ZafUInt32)0);
		returnValue += Write((ZafUInt32)0);
		return (returnValue);
	}
	bool sign = (value < 0);
	int exponent;
	double mantissa = frexp(value, &exponent);

	// Normalize the exponent and mantissa.
	// Subtract 1 because of hidden bit in mantissa.
	exponent = exponent + 1023 - 1;
//	ZafUInt32 tempLong = exponent;
//	tempLong = (tempLong << 20);
//	tempLong = tempLong & 0x7fffffffL;
//	convert.hex[0] = tempLong;
	convert.hex[0] = ((ZafUInt32)exponent) << 20;
//	convert.hex[0] << 20;

	// Set the sign and mantissa bits.
	convert.hex[0] |= (sign) ? 0x80000000L : 0;
	mantissa = (mantissa * 2.0 ) - 1.0;
	ZafUInt32 bitPosition = 0x00080000L;
	for (; bitPosition && mantissa != 0.0; bitPosition = bitPosition >> 1)
	{
		mantissa *= 2.0;
		if (mantissa >= 1.0)
		{
			mantissa -= 1.0;
			convert.hex[0] |= bitPosition;
		}

	}

	bitPosition = 0x80000000L;
	for (; bitPosition && mantissa != 0.0; bitPosition = bitPosition >> 1)
	{
		mantissa *= 2.0;
		if (mantissa >= 1.0)
		{
			mantissa -= 1.0;
			convert.hex[1] |= bitPosition;
		}

	}

	// Write as a pair of ZafUInt32 to take care of byte swapping.
	returnValue = Write(convert.hex[0]);
	returnValue += Write(convert.hex[1]);

#endif

	return (returnValue);
}

