X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d699f48ba33c96c24f7ab3764ad98ded0633c1c5..bba35861478a26f5d8c756a9a7fa2bbd19a69cb1:/src/common/extended.c?ds=inline diff --git a/src/common/extended.c b/src/common/extended.c index f81792f6d6..6844663420 100644 --- a/src/common/extended.c +++ b/src/common/extended.c @@ -1,20 +1,54 @@ +/***************************************************************************** +** Name: extended.c +** Purpose: IEEE Extended<->Double routines to save floats to file +** Maintainer: Ryan Norton +** Modified by: +** Created: 11/24/04 +** RCS-ID: $Id$ +*****************************************************************************/ + + +#if defined(_WIN32_WCE) + /* eVC cause warnings in its own headers: stdlib.h and winnt.h */ + #pragma warning (disable:4115) + #pragma warning (disable:4214) +#endif + +#include +#include +#include +#include +#include #include "wx/defs.h" -#include +#if defined(_WIN32_WCE) + #pragma warning (default:4115) + #pragma warning (default:4214) +#endif #if wxUSE_APPLE_IEEE -/* - * C O N V E R T T O I E E E E X T E N D E D - */ +#include "wx/math.h" -/* Copyright (C) 1988-1991 Apple Computer, Inc. +/* Copyright (C) 1989-1991 Ken Turkowski. + * * All rights reserved. * + * Warranty Information + * Even though I have reviewed this software, I make no warranty + * or representation, either express or implied, with respect to this + * software, its quality, accuracy, merchantability, or fitness for a + * particular purpose. As a result, this software is provided "as is," + * and you, its user, are assuming the entire risk as to its quality + * and accuracy. + * + * This code may be used and freely distributed as long as it includes + * this copyright notice and the above warranty information. + * * Machine-independent I/O routines for IEEE floating-point numbers. * * NaN's and infinities are converted to HUGE_VAL or HUGE, which - * happens to be infinity on IEEE machines. Unfortunately, it is + * happens to be infinity on IEEE machines. Unfortunately, it is * impossible to preserve NaN's in a machine-independent way. * Infinities are, however, preserved on IEEE machines. * @@ -24,6 +58,8 @@ * Silicon Graphics IRIS, MIPS compiler * Cray X/MP and Y/MP * Digital Equipment VAX + * Sequent Balance (Multiprocesor 386) + * NeXT * * * Implemented by Malcolm Slaney and Ken Turkowski. @@ -40,140 +76,56 @@ */ #ifndef HUGE_VAL -#define HUGE_VAL HUGE +# define HUGE_VAL HUGE #endif /*HUGE_VAL*/ -#define FloatToUnsigned(f) ((unsigned long) (((long) (f - 2147483648.0)) + 2147483647L) + 1) - -void ConvertToIeeeExtended(double num, unsigned char *bytes) -{ - int sign; - int expon; - double fMant, fsMant; - unsigned long hiMant, loMant; - if (num < 0) { - sign = 0x8000; - num *= -1; - } else { - sign = 0; - } +/**************************************************************** + * The following two routines make up for deficiencies in many + * compilers to convert properly between unsigned integers and + * floating-point. Some compilers which have this bug are the + * THINK_C compiler for the Macintosh and the C compiler for the + * Silicon Graphics MIPS-based Iris. + ****************************************************************/ - if (num == 0) { - expon = 0; hiMant = 0; loMant = 0; - } - else { - fMant = frexp(num, &expon); - if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */ - expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */ - } - else { /* Finite */ - expon += 16382; - if (expon < 0) { /* denormalized */ - fMant = ldexp(fMant, expon); - expon = 0; - } - expon |= sign; - fMant = ldexp(fMant, 32); - fsMant = floor(fMant); - hiMant = FloatToUnsigned(fsMant); - fMant = ldexp(fMant - fsMant, 32); - fsMant = floor(fMant); - loMant = FloatToUnsigned(fsMant); - } - } +#ifdef applec /* The Apple C compiler works */ +# define FloatToUnsigned(f) ((wxUint32)(f)) +# define UnsignedToFloat(u) ((wxFloat64)(u)) +#else /*applec*/ +# define FloatToUnsigned(f) ((wxUint32)(((wxInt32)((f) - 2147483648.0)) + 2147483647L) + 1) +# define UnsignedToFloat(u) (((wxFloat64)((wxInt32)((u) - 2147483647L - 1))) + 2147483648.0) +#endif /*applec*/ - /* disable the warning about 'possible loss of data' & 'conversion between - * diff types' */ -#ifdef _MSC_VER -#pragma warning(disable: 4244) -#pragma warning(disable: 4135) -#endif /* Visual C++ */ - - bytes[0] = (expon >> 8) & 0xff; - bytes[1] = expon & 0xff; - bytes[2] = (unsigned char) ((hiMant >> 24) & 0xff); - bytes[3] = (unsigned char) ((hiMant >> 16) & 0xff); - bytes[4] = (unsigned char) ((hiMant >> 8) & 0xff); - bytes[5] = (unsigned char) (hiMant & 0xff); - bytes[6] = (unsigned char) ((loMant >> 24) & 0xff); - bytes[7] = (unsigned char) ((loMant >> 16) & 0xff); - bytes[8] = (unsigned char) ((loMant >> 8) & 0xff); - bytes[9] = (unsigned char) (loMant & 0xff); - -#ifdef _MSC_VER -#pragma warning(default: 4244) -#pragma warning(default: 4135) -#endif /* Visual C++ */ -} -/* - * C O N V E R T F R O M I E E E E X T E N D E D - */ - -/* - * Copyright (C) 1988-1991 Apple Computer, Inc. - * All rights reserved. - * - * Machine-independent I/O routines for IEEE floating-point numbers. - * - * NaN's and infinities are converted to HUGE_VAL or HUGE, which - * happens to be infinity on IEEE machines. Unfortunately, it is - * impossible to preserve NaN's in a machine-independent way. - * Infinities are, however, preserved on IEEE machines. - * - * These routines have been tested on the following machines: - * Apple Macintosh, MPW 3.1 C compiler - * Apple Macintosh, THINK C compiler - * Silicon Graphics IRIS, MIPS compiler - * Cray X/MP and Y/MP - * Digital Equipment VAX - * - * - * Implemented by Malcolm Slaney and Ken Turkowski. - * - * Malcolm Slaney contributions during 1988-1990 include big- and little- - * endian file I/O, conversion to and from Motorola's extended 80-bit - * floating-point format, and conversions to and from IEEE single- - * precision floating-point format. - * - * In 1991, Ken Turkowski implemented the conversions to and from - * IEEE double-precision format, added more precision to the extended - * conversions, and accommodated conversions involving +/- infinity, - * NaN's, and denormalized numbers. - */ - -#ifndef HUGE_VAL -# define HUGE_VAL HUGE -#endif /*HUGE_VAL*/ - -# define UnsignedToFloat(u) (((double) ((long) (u - 2147483647L - 1))) + 2147483648.0) /**************************************************************** - * Extended precision IEEE floating-point conversion routine. + * Extended precision IEEE floating-point conversion routines. + * Extended is an 80-bit number as defined by Motorola, + * with a sign bit, 15 bits of exponent (offset 16383?), + * and a 64-bit mantissa, with no hidden bit. ****************************************************************/ -double ConvertFromIeeeExtended(const unsigned char *bytes) +WXDLLIMPEXP_BASE wxFloat64 wxConvertFromIeeeExtended(const wxInt8 *bytes) { - double f; - int expon; - unsigned long hiMant, loMant; + wxFloat64 f; + wxInt32 expon; + wxUint32 hiMant, loMant; expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF); - hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24) - | ((unsigned long) (bytes[3] & 0xFF) << 16) - | ((unsigned long) (bytes[4] & 0xFF) << 8) - | ((unsigned long) (bytes[5] & 0xFF)); - loMant = ((unsigned long) (bytes[6] & 0xFF) << 24) - | ((unsigned long) (bytes[7] & 0xFF) << 16) - | ((unsigned long) (bytes[8] & 0xFF) << 8) - | ((unsigned long) (bytes[9] & 0xFF)); + hiMant = ((wxUint32)(bytes[2] & 0xFF) << 24) + | ((wxUint32)(bytes[3] & 0xFF) << 16) + | ((wxUint32)(bytes[4] & 0xFF) << 8) + | ((wxUint32)(bytes[5] & 0xFF)); + loMant = ((wxUint32)(bytes[6] & 0xFF) << 24) + | ((wxUint32)(bytes[7] & 0xFF) << 16) + | ((wxUint32)(bytes[8] & 0xFF) << 8) + | ((wxUint32)(bytes[9] & 0xFF)); if (expon == 0 && hiMant == 0 && loMant == 0) { f = 0; } else { - if (expon == 0x7FFF) { /* Infinity or NaN */ + if (expon == 0x7FFF) { /* Infinity or NaN */ f = HUGE_VAL; } else { @@ -189,4 +141,66 @@ double ConvertFromIeeeExtended(const unsigned char *bytes) return f; } + +/****************************************************************/ + + +WXDLLIMPEXP_BASE void wxConvertToIeeeExtended(wxFloat64 num, wxInt8 *bytes) +{ + wxInt32 sign; + wxInt32 expon; + wxFloat64 fMant, fsMant; + wxUint32 hiMant, loMant; + + if (num < 0) { + sign = 0x8000; + num *= -1; + } else { + sign = 0; + } + + if (num == 0) { + expon = 0; hiMant = 0; loMant = 0; + } + else { + fMant = frexp(num, &expon); + if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */ + expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */ + } + else { /* Finite */ + expon += 16382; + if (expon < 0) { /* denormalized */ + fMant = ldexp(fMant, expon); + expon = 0; + } + expon |= sign; + fMant = ldexp(fMant, 32); fsMant = floor(fMant); hiMant = FloatToUnsigned(fsMant); + fMant = ldexp(fMant - fsMant, 32); fsMant = floor(fMant); loMant = FloatToUnsigned(fsMant); + } + } + + bytes[0] = expon >> 8; + bytes[1] = expon; + bytes[2] = hiMant >> 24; + bytes[3] = hiMant >> 16; + bytes[4] = hiMant >> 8; + bytes[5] = hiMant; + bytes[6] = loMant >> 24; + bytes[7] = loMant >> 16; + bytes[8] = loMant >> 8; + bytes[9] = loMant; +} + +#if WXWIN_COMPATIBILITY_2_8 +WXDLLIMPEXP_BASE wxFloat64 ConvertFromIeeeExtended(const wxInt8 *bytes) +{ + return wxConvertFromIeeeExtended(bytes); +} + +WXDLLIMPEXP_BASE void ConvertToIeeeExtended(wxFloat64 num, wxInt8 *bytes) +{ + wxConvertToIeeeExtended(num, bytes); +} +#endif // WXWIN_COMPATIBILITY_2_8 + #endif /* wxUSE_APPLE_IEEE */