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