Small changes
[wxWidgets.git] / src / common / extended.c
1 #include "wx/setup.h"
2 #include <math.h>
3
4 #if wxUSE_APPLE_IEEE
5
6 /*
7 * C O N V E R T T O I E E E E X T E N D E D
8 */
9
10 /* Copyright (C) 1988-1991 Apple Computer, Inc.
11 * All rights reserved.
12 *
13 * Machine-independent I/O routines for IEEE floating-point numbers.
14 *
15 * NaN's and infinities are converted to HUGE_VAL or HUGE, which
16 * happens to be infinity on IEEE machines. Unfortunately, it is
17 * impossible to preserve NaN's in a machine-independent way.
18 * Infinities are, however, preserved on IEEE machines.
19 *
20 * These routines have been tested on the following machines:
21 * Apple Macintosh, MPW 3.1 C compiler
22 * Apple Macintosh, THINK C compiler
23 * Silicon Graphics IRIS, MIPS compiler
24 * Cray X/MP and Y/MP
25 * Digital Equipment VAX
26 *
27 *
28 * Implemented by Malcolm Slaney and Ken Turkowski.
29 *
30 * Malcolm Slaney contributions during 1988-1990 include big- and little-
31 * endian file I/O, conversion to and from Motorola's extended 80-bit
32 * floating-point format, and conversions to and from IEEE single-
33 * precision floating-point format.
34 *
35 * In 1991, Ken Turkowski implemented the conversions to and from
36 * IEEE double-precision format, added more precision to the extended
37 * conversions, and accommodated conversions involving +/- infinity,
38 * NaN's, and denormalized numbers.
39 */
40
41 #ifndef HUGE_VAL
42 #define HUGE_VAL HUGE
43 #endif /*HUGE_VAL*/
44
45 #define FloatToUnsigned(f) ((unsigned long) (((long) (f - 2147483648.0)) + 2147483647L) + 1)
46
47 void ConvertToIeeeExtended(double num, unsigned char *bytes)
48 {
49 int sign;
50 int expon;
51 double fMant, fsMant;
52 unsigned long hiMant, loMant;
53
54 if (num < 0) {
55 sign = 0x8000;
56 num *= -1;
57 } else {
58 sign = 0;
59 }
60
61 if (num == 0) {
62 expon = 0; hiMant = 0; loMant = 0;
63 }
64 else {
65 fMant = frexp(num, &expon);
66 if ((expon > 16384) || !(fMant < 1)) { /* Infinity or NaN */
67 expon = sign|0x7FFF; hiMant = 0; loMant = 0; /* infinity */
68 }
69 else { /* Finite */
70 expon += 16382;
71 if (expon < 0) { /* denormalized */
72 fMant = ldexp(fMant, expon);
73 expon = 0;
74 }
75 expon |= sign;
76 fMant = ldexp(fMant, 32);
77 fsMant = floor(fMant);
78 hiMant = FloatToUnsigned(fsMant);
79 fMant = ldexp(fMant - fsMant, 32);
80 fsMant = floor(fMant);
81 loMant = FloatToUnsigned(fsMant);
82 }
83 }
84
85 /* disable the warning about 'possible loss of data' */
86 #ifdef _MSC_VER
87 #pragma warning(disable: 4244)
88 #endif /* Visual C++ */
89
90 bytes[0] = expon >> 8;
91 bytes[1] = expon;
92 bytes[2] = (unsigned char) hiMant >> 24;
93 bytes[3] = (unsigned char) hiMant >> 16;
94 bytes[4] = (unsigned char) hiMant >> 8;
95 bytes[5] = (unsigned char) hiMant;
96 bytes[6] = (unsigned char) loMant >> 24;
97 bytes[7] = (unsigned char) loMant >> 16;
98 bytes[8] = (unsigned char) loMant >> 8;
99 bytes[9] = (unsigned char) loMant;
100
101 #ifdef _MSC_VER
102 #pragma warning(default: 4244)
103 #endif /* Visual C++ */
104 }
105
106 /*
107 * C O N V E R T F R O M I E E E E X T E N D E D
108 */
109
110 /*
111 * Copyright (C) 1988-1991 Apple Computer, Inc.
112 * All rights reserved.
113 *
114 * Machine-independent I/O routines for IEEE floating-point numbers.
115 *
116 * NaN's and infinities are converted to HUGE_VAL or HUGE, which
117 * happens to be infinity on IEEE machines. Unfortunately, it is
118 * impossible to preserve NaN's in a machine-independent way.
119 * Infinities are, however, preserved on IEEE machines.
120 *
121 * These routines have been tested on the following machines:
122 * Apple Macintosh, MPW 3.1 C compiler
123 * Apple Macintosh, THINK C compiler
124 * Silicon Graphics IRIS, MIPS compiler
125 * Cray X/MP and Y/MP
126 * Digital Equipment VAX
127 *
128 *
129 * Implemented by Malcolm Slaney and Ken Turkowski.
130 *
131 * Malcolm Slaney contributions during 1988-1990 include big- and little-
132 * endian file I/O, conversion to and from Motorola's extended 80-bit
133 * floating-point format, and conversions to and from IEEE single-
134 * precision floating-point format.
135 *
136 * In 1991, Ken Turkowski implemented the conversions to and from
137 * IEEE double-precision format, added more precision to the extended
138 * conversions, and accommodated conversions involving +/- infinity,
139 * NaN's, and denormalized numbers.
140 */
141
142 #ifndef HUGE_VAL
143 # define HUGE_VAL HUGE
144 #endif /*HUGE_VAL*/
145
146 # define UnsignedToFloat(u) (((double) ((long) (u - 2147483647L - 1))) + 2147483648.0)
147
148 /****************************************************************
149 * Extended precision IEEE floating-point conversion routine.
150 ****************************************************************/
151
152 double ConvertFromIeeeExtended(const unsigned char *bytes)
153 {
154 double f;
155 int expon;
156 unsigned long hiMant, loMant;
157
158 expon = ((bytes[0] & 0x7F) << 8) | (bytes[1] & 0xFF);
159 hiMant = ((unsigned long)(bytes[2] & 0xFF) << 24)
160 | ((unsigned long) (bytes[3] & 0xFF) << 16)
161 | ((unsigned long) (bytes[4] & 0xFF) << 8)
162 | ((unsigned long) (bytes[5] & 0xFF));
163 loMant = ((unsigned long) (bytes[6] & 0xFF) << 24)
164 | ((unsigned long) (bytes[7] & 0xFF) << 16)
165 | ((unsigned long) (bytes[8] & 0xFF) << 8)
166 | ((unsigned long) (bytes[9] & 0xFF));
167
168 if (expon == 0 && hiMant == 0 && loMant == 0) {
169 f = 0;
170 }
171 else {
172 if (expon == 0x7FFF) { /* Infinity or NaN */
173 f = HUGE_VAL;
174 }
175 else {
176 expon -= 16383;
177 f = ldexp(UnsignedToFloat(hiMant), expon-=31);
178 f += ldexp(UnsignedToFloat(loMant), expon-=32);
179 }
180 }
181
182 if (bytes[0] & 0x80)
183 return -f;
184 else
185 return f;
186 }
187
188 #endif /* wxUSE_APPLE_IEEE */