1 /*****************************************************************************
2 ** Name:        extended.c
3 ** Purpose:     IEEE Extended<->Double routines to save floats to file
4 ** Maintainer:  Ryan Norton
5 ** Modified by:
6 ** Created:     11/24/04
7 ** RCS-ID:      $Id: extended.c 36952 2006-01-18 10:25:04Z JS $
8 *****************************************************************************/
9 
10 
11 #if defined(_WIN32_WCE)
12     /* eVC cause warnings in its own headers: stdlib.h and winnt.h */
13     #pragma warning (disable:4115)
14     #pragma warning (disable:4214)
15 #endif
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <ctype.h>
20 #include <limits.h>
21 #include <string.h>
22 #include "wx/defs.h"
23 
24 #if defined(_WIN32_WCE)
25     #pragma warning (default:4115)
26     #pragma warning (default:4214)
27 #endif
28 
29 #if wxUSE_APPLE_IEEE
30 
31 #include "wx/math.h"
32 
33 /* Copyright (C) 1989-1991 Ken Turkowski. <turk@computer.org>
34  *
35  * All rights reserved.
36  *
37  * Warranty Information
38  *  Even though I have reviewed this software, I make no warranty
39  *  or representation, either express or implied, with respect to this
40  *  software, its quality, accuracy, merchantability, or fitness for a
41  *  particular purpose.  As a result, this software is provided "as is,"
42  *  and you, its user, are assuming the entire risk as to its quality
43  *  and accuracy.
44  *
45  * This code may be used and freely distributed as long as it includes
46  * this copyright notice and the above warranty information.
47  *
48  * Machine-independent I/O routines for IEEE floating-point numbers.
49  *
50  * NaN's and infinities are converted to HUGE_VAL or HUGE, which
51  * happens to be infinity on IEEE machines.  Unfortunately, it is
52  * impossible to preserve NaN's in a machine-independent way.
53  * Infinities are, however, preserved on IEEE machines.
54  *
55  * These routines have been tested on the following machines:
56  *    Apple Macintosh, MPW 3.1 C compiler
57  *    Apple Macintosh, THINK C compiler
58  *    Silicon Graphics IRIS, MIPS compiler
59  *    Cray X/MP and Y/MP
60  *    Digital Equipment VAX
61  *    Sequent Balance (Multiprocesor 386)
62  *    NeXT
63  *
64  *
65  * Implemented by Malcolm Slaney and Ken Turkowski.
66  *
67  * Malcolm Slaney contributions during 1988-1990 include big- and little-
68  * endian file I/O, conversion to and from Motorola's extended 80-bit
69  * floating-point format, and conversions to and from IEEE single-
70  * precision floating-point format.
71  *
72  * In 1991, Ken Turkowski implemented the conversions to and from
73  * IEEE double-precision format, added more precision to the extended
74  * conversions, and accommodated conversions involving +/- infinity,
75  * NaN's, and denormalized numbers.
76  */
77 
78 #ifndef HUGE_VAL
79 # define HUGE_VAL HUGE
80 #endif /*HUGE_VAL*/
81 
82 
83 /****************************************************************
84  * The following two routines make up for deficiencies in many
85  * compilers to convert properly between unsigned integers and
86  * floating-point.  Some compilers which have this bug are the
87  * THINK_C compiler for the Macintosh and the C compiler for the
88  * Silicon Graphics MIPS-based Iris.
89  ****************************************************************/
90 
91 #ifdef applec    /* The Apple C compiler works */
92 # define FloatToUnsigned(f)   ((wxUint32)(f))
93 # define UnsignedToFloat(u)   ((wxFloat64)(u))
94 #else /*applec*/
95 # define FloatToUnsigned(f)   ((wxUint32)(((wxInt32)((f) - 2147483648.0)) + 2147483647L) + 1)
96 # define UnsignedToFloat(u)   (((wxFloat64)((wxInt32)((u) - 2147483647L - 1))) + 2147483648.0)
97 #endif /*applec*/
98 
99 
100 
101 /****************************************************************
102  * Extended precision IEEE floating-point conversion routines.
103  * Extended is an 80-bit number as defined by Motorola,
104  * with a sign bit, 15 bits of exponent (offset 16383?),
105  * and a 64-bit mantissa, with no hidden bit.
106  ****************************************************************/
107 
ConvertFromIeeeExtended(const wxInt8 * bytes)108 wxFloat64 ConvertFromIeeeExtended(const wxInt8 *bytes)
109 {
110     wxFloat64 f;
111     wxInt32 expon;
112     wxUint32 hiMant, loMant;
113 
114     expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
115     hiMant = ((wxUint32)(bytes[2] & 0xFF) << 24)
116             | ((wxUint32)(bytes[3] & 0xFF) << 16)
117             | ((wxUint32)(bytes[4] & 0xFF) << 8)
118             | ((wxUint32)(bytes[5] & 0xFF));
119     loMant = ((wxUint32)(bytes[6] & 0xFF) << 24)
120             | ((wxUint32)(bytes[7] & 0xFF) << 16)
121             | ((wxUint32)(bytes[8] & 0xFF) << 8)
122             | ((wxUint32)(bytes[9] & 0xFF));
123 
124     if (expon == 0 && hiMant == 0 && loMant == 0) {
125         f = 0;
126     }
127     else {
128         if (expon == 0x7FFF) { /* Infinity or NaN */
129             f = HUGE_VAL;
130         }
131         else {
132             expon -= 16383;
133             f  = ldexp(UnsignedToFloat(hiMant), expon-=31);
134             f += ldexp(UnsignedToFloat(loMant), expon-=32);
135         }
136     }
137 
138     if (bytes[0] & 0x80)
139         return -f;
140     else
141         return f;
142 }
143 
144 
145 /****************************************************************/
146 
147 
ConvertToIeeeExtended(wxFloat64 num,wxInt8 * bytes)148 void ConvertToIeeeExtended(wxFloat64 num, wxInt8 *bytes)
149 {
150     wxInt32 sign;
151     wxInt32 expon;
152     wxFloat64 fMant, fsMant;
153     wxUint32 hiMant, loMant;
154 
155     if (num < 0) {
156         sign = 0x8000;
157         num *= -1;
158     } else {
159         sign = 0;
160     }
161 
162     if (num == 0) {
163         expon = 0; hiMant = 0; loMant = 0;
164     }
165     else {
166         fMant = frexp(num, &expon);
167         if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */
168             expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
169         }
170         else { /* Finite */
171             expon += 16382;
172             if (expon < 0) { /* denormalized */
173                 fMant = ldexp(fMant, expon);
174                 expon = 0;
175             }
176             expon |= sign;
177             fMant = ldexp(fMant, 32);          fsMant = floor(fMant); hiMant = FloatToUnsigned(fsMant);
178             fMant = ldexp(fMant - fsMant, 32); fsMant = floor(fMant); loMant = FloatToUnsigned(fsMant);
179         }
180     }
181 
182     bytes[0] = expon >> 8;
183     bytes[1] = expon;
184     bytes[2] = hiMant >> 24;
185     bytes[3] = hiMant >> 16;
186     bytes[4] = hiMant >> 8;
187     bytes[5] = hiMant;
188     bytes[6] = loMant >> 24;
189     bytes[7] = loMant >> 16;
190     bytes[8] = loMant >> 8;
191     bytes[9] = loMant;
192 }
193 
194 
195 
196 #endif /* wxUSE_APPLE_IEEE */
197