Add IEEE 754 single/double precision support to wxDataStream classes.

Allow to optionally raed/write float/double values in IEEE 754 single/double
precision formats, respectively, instead of always using the extended
precision format for both of them.

This makes the code more flexible, allowing for better interoperability with
the other programs, and also allows to implement floating point functions in
these classes even when wxUSE_APPLE_IEEE is turned off (as can be the case
because of the licencing concerns for the code in extended.c).

Closes #10625.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73938 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2013-05-06 00:31:03 +00:00
parent be2a424da6
commit 789ab84044
6 changed files with 327 additions and 31 deletions

View File

@@ -24,6 +24,24 @@
#include "wx/math.h"
#endif //WX_PRECOMP
namespace
{
// helper unions used to swap bytes of floats and doubles
union Float32Data
{
wxFloat32 f;
wxUint32 i;
};
union Float64Data
{
wxFloat64 f;
wxUint32 i[2];
};
} // anonymous namespace
// ----------------------------------------------------------------------------
// wxDataStreamBase
// ----------------------------------------------------------------------------
@@ -37,6 +55,12 @@ wxDataStreamBase::wxDataStreamBase(const wxMBConv& conv)
wxUnusedVar(conv);
m_be_order = false;
// For compatibility with the existing data files, we use extended
// precision if it is available, i.e. if wxUSE_APPLE_IEEE is on.
#if wxUSE_APPLE_IEEE
m_useExtendedPrecision = true;
#endif // wxUSE_APPLE_IEEE
}
#if wxUSE_UNICODE
@@ -108,13 +132,48 @@ wxUint8 wxDataInputStream::Read8()
double wxDataInputStream::ReadDouble()
{
#if wxUSE_APPLE_IEEE
char buf[10];
if ( m_useExtendedPrecision )
{
char buf[10];
m_input->Read(buf, 10);
return wxConvertFromIeeeExtended((const wxInt8 *)buf);
#else
return 0.0;
#endif
m_input->Read(buf, 10);
return wxConvertFromIeeeExtended((const wxInt8 *)buf);
}
else
#endif // wxUSE_APPLE_IEEE
{
Float64Data floatData;
if ( m_be_order == (wxBYTE_ORDER == wxBIG_ENDIAN) )
{
floatData.i[0] = Read32();
floatData.i[1] = Read32();
}
else
{
floatData.i[1] = Read32();
floatData.i[0] = Read32();
}
return static_cast<double>(floatData.f);
}
}
float wxDataInputStream::ReadFloat()
{
#if wxUSE_APPLE_IEEE
if ( m_useExtendedPrecision )
{
return (float)ReadDouble();
}
else
#endif // wxUSE_APPLE_IEEE
{
Float32Data floatData;
floatData.i = Read32();
return static_cast<float>(floatData.f);
}
}
wxString wxDataInputStream::ReadString()
@@ -388,6 +447,14 @@ void wxDataInputStream::ReadDouble(double *buffer, size_t size)
}
}
void wxDataInputStream::ReadFloat(float *buffer, size_t size)
{
for (wxUint32 i=0; i<size; i++)
{
*(buffer++) = ReadFloat();
}
}
wxDataInputStream& wxDataInputStream::operator>>(wxString& s)
{
s = ReadString();
@@ -466,7 +533,7 @@ wxDataInputStream& wxDataInputStream::operator>>(double& d)
wxDataInputStream& wxDataInputStream::operator>>(float& f)
{
f = (float)ReadDouble();
f = ReadFloat();
return *this;
}
@@ -535,22 +602,49 @@ void wxDataOutputStream::WriteString(const wxString& string)
void wxDataOutputStream::WriteDouble(double d)
{
char buf[10];
#if wxUSE_APPLE_IEEE
wxConvertToIeeeExtended(d, (wxInt8 *)buf);
#else
wxUnusedVar(d);
#if !defined(__VMS__) && !defined(__GNUG__)
#ifdef _MSC_VER
# pragma message("wxDataOutputStream::WriteDouble() not using IeeeExtended - will not work!")
#else
# pragma warning "wxDataOutputStream::WriteDouble() not using IeeeExtended - will not work!"
#endif
#endif
buf[0] = '\0';
#endif
m_output->Write(buf, 10);
if ( m_useExtendedPrecision )
{
char buf[10];
wxConvertToIeeeExtended(d, (wxInt8 *)buf);
m_output->Write(buf, 10);
}
else
#endif // wxUSE_APPLE_IEEE
{
Float64Data floatData;
floatData.f = (wxFloat64)d;
if ( m_be_order == (wxBYTE_ORDER == wxBIG_ENDIAN) )
{
Write32(floatData.i[0]);
Write32(floatData.i[1]);
}
else
{
Write32(floatData.i[1]);
Write32(floatData.i[0]);
}
}
}
void wxDataOutputStream::WriteFloat(float f)
{
#if wxUSE_APPLE_IEEE
if ( m_useExtendedPrecision )
{
WriteDouble((double)f);
}
else
#endif // wxUSE_APPLE_IEEE
{
Float32Data floatData;
floatData.f = (wxFloat32)f;
Write32(floatData.i);
}
}
#if wxHAS_INT64
@@ -664,6 +758,14 @@ void wxDataOutputStream::WriteDouble(const double *buffer, size_t size)
}
}
void wxDataOutputStream::WriteFloat(const float *buffer, size_t size)
{
for (wxUint32 i=0; i<size; i++)
{
WriteFloat(*(buffer++));
}
}
wxDataOutputStream& wxDataOutputStream::operator<<(const wxString& string)
{
WriteString(string);
@@ -742,7 +844,7 @@ wxDataOutputStream& wxDataOutputStream::operator<<(double d)
wxDataOutputStream& wxDataOutputStream::operator<<(float f)
{
WriteDouble((double)f);
WriteFloat(f);
return *this;
}