1*e4b17023SJohn Marino /* IEEE floating point support routines, for GDB, the GNU Debugger.
2*e4b17023SJohn Marino Copyright 1991, 1994, 1999, 2000, 2003, 2005, 2006, 2010
3*e4b17023SJohn Marino Free Software Foundation, Inc.
4*e4b17023SJohn Marino
5*e4b17023SJohn Marino This file is part of GDB.
6*e4b17023SJohn Marino
7*e4b17023SJohn Marino This program is free software; you can redistribute it and/or modify
8*e4b17023SJohn Marino it under the terms of the GNU General Public License as published by
9*e4b17023SJohn Marino the Free Software Foundation; either version 2 of the License, or
10*e4b17023SJohn Marino (at your option) any later version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino This program is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15*e4b17023SJohn Marino GNU General Public License for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with this program; if not, write to the Free Software
19*e4b17023SJohn Marino Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino /* This is needed to pick up the NAN macro on some systems. */
22*e4b17023SJohn Marino #define _GNU_SOURCE
23*e4b17023SJohn Marino
24*e4b17023SJohn Marino #ifdef HAVE_CONFIG_H
25*e4b17023SJohn Marino #include "config.h"
26*e4b17023SJohn Marino #endif
27*e4b17023SJohn Marino
28*e4b17023SJohn Marino #include <math.h>
29*e4b17023SJohn Marino
30*e4b17023SJohn Marino #ifdef HAVE_STRING_H
31*e4b17023SJohn Marino #include <string.h>
32*e4b17023SJohn Marino #endif
33*e4b17023SJohn Marino
34*e4b17023SJohn Marino /* On some platforms, <float.h> provides DBL_QNAN. */
35*e4b17023SJohn Marino #ifdef STDC_HEADERS
36*e4b17023SJohn Marino #include <float.h>
37*e4b17023SJohn Marino #endif
38*e4b17023SJohn Marino
39*e4b17023SJohn Marino #include "ansidecl.h"
40*e4b17023SJohn Marino #include "libiberty.h"
41*e4b17023SJohn Marino #include "floatformat.h"
42*e4b17023SJohn Marino
43*e4b17023SJohn Marino #ifndef INFINITY
44*e4b17023SJohn Marino #ifdef HUGE_VAL
45*e4b17023SJohn Marino #define INFINITY HUGE_VAL
46*e4b17023SJohn Marino #else
47*e4b17023SJohn Marino #define INFINITY (1.0 / 0.0)
48*e4b17023SJohn Marino #endif
49*e4b17023SJohn Marino #endif
50*e4b17023SJohn Marino
51*e4b17023SJohn Marino #ifndef NAN
52*e4b17023SJohn Marino #ifdef DBL_QNAN
53*e4b17023SJohn Marino #define NAN DBL_QNAN
54*e4b17023SJohn Marino #else
55*e4b17023SJohn Marino #define NAN (0.0 / 0.0)
56*e4b17023SJohn Marino #endif
57*e4b17023SJohn Marino #endif
58*e4b17023SJohn Marino
59*e4b17023SJohn Marino static int mant_bits_set (const struct floatformat *, const unsigned char *);
60*e4b17023SJohn Marino static unsigned long get_field (const unsigned char *,
61*e4b17023SJohn Marino enum floatformat_byteorders,
62*e4b17023SJohn Marino unsigned int,
63*e4b17023SJohn Marino unsigned int,
64*e4b17023SJohn Marino unsigned int);
65*e4b17023SJohn Marino static int floatformat_always_valid (const struct floatformat *fmt,
66*e4b17023SJohn Marino const void *from);
67*e4b17023SJohn Marino
68*e4b17023SJohn Marino static int
floatformat_always_valid(const struct floatformat * fmt ATTRIBUTE_UNUSED,const void * from ATTRIBUTE_UNUSED)69*e4b17023SJohn Marino floatformat_always_valid (const struct floatformat *fmt ATTRIBUTE_UNUSED,
70*e4b17023SJohn Marino const void *from ATTRIBUTE_UNUSED)
71*e4b17023SJohn Marino {
72*e4b17023SJohn Marino return 1;
73*e4b17023SJohn Marino }
74*e4b17023SJohn Marino
75*e4b17023SJohn Marino /* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not
76*e4b17023SJohn Marino going to bother with trying to muck around with whether it is defined in
77*e4b17023SJohn Marino a system header, what we do if not, etc. */
78*e4b17023SJohn Marino #define FLOATFORMAT_CHAR_BIT 8
79*e4b17023SJohn Marino
80*e4b17023SJohn Marino /* floatformats for IEEE half, single and double, big and little endian. */
81*e4b17023SJohn Marino const struct floatformat floatformat_ieee_half_big =
82*e4b17023SJohn Marino {
83*e4b17023SJohn Marino floatformat_big, 16, 0, 1, 5, 15, 31, 6, 10,
84*e4b17023SJohn Marino floatformat_intbit_no,
85*e4b17023SJohn Marino "floatformat_ieee_half_big",
86*e4b17023SJohn Marino floatformat_always_valid,
87*e4b17023SJohn Marino NULL
88*e4b17023SJohn Marino };
89*e4b17023SJohn Marino const struct floatformat floatformat_ieee_half_little =
90*e4b17023SJohn Marino {
91*e4b17023SJohn Marino floatformat_little, 16, 0, 1, 5, 15, 31, 6, 10,
92*e4b17023SJohn Marino floatformat_intbit_no,
93*e4b17023SJohn Marino "floatformat_ieee_half_little",
94*e4b17023SJohn Marino floatformat_always_valid,
95*e4b17023SJohn Marino NULL
96*e4b17023SJohn Marino };
97*e4b17023SJohn Marino const struct floatformat floatformat_ieee_single_big =
98*e4b17023SJohn Marino {
99*e4b17023SJohn Marino floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23,
100*e4b17023SJohn Marino floatformat_intbit_no,
101*e4b17023SJohn Marino "floatformat_ieee_single_big",
102*e4b17023SJohn Marino floatformat_always_valid,
103*e4b17023SJohn Marino NULL
104*e4b17023SJohn Marino };
105*e4b17023SJohn Marino const struct floatformat floatformat_ieee_single_little =
106*e4b17023SJohn Marino {
107*e4b17023SJohn Marino floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23,
108*e4b17023SJohn Marino floatformat_intbit_no,
109*e4b17023SJohn Marino "floatformat_ieee_single_little",
110*e4b17023SJohn Marino floatformat_always_valid,
111*e4b17023SJohn Marino NULL
112*e4b17023SJohn Marino };
113*e4b17023SJohn Marino const struct floatformat floatformat_ieee_double_big =
114*e4b17023SJohn Marino {
115*e4b17023SJohn Marino floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52,
116*e4b17023SJohn Marino floatformat_intbit_no,
117*e4b17023SJohn Marino "floatformat_ieee_double_big",
118*e4b17023SJohn Marino floatformat_always_valid,
119*e4b17023SJohn Marino NULL
120*e4b17023SJohn Marino };
121*e4b17023SJohn Marino const struct floatformat floatformat_ieee_double_little =
122*e4b17023SJohn Marino {
123*e4b17023SJohn Marino floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52,
124*e4b17023SJohn Marino floatformat_intbit_no,
125*e4b17023SJohn Marino "floatformat_ieee_double_little",
126*e4b17023SJohn Marino floatformat_always_valid,
127*e4b17023SJohn Marino NULL
128*e4b17023SJohn Marino };
129*e4b17023SJohn Marino
130*e4b17023SJohn Marino /* floatformat for IEEE double, little endian byte order, with big endian word
131*e4b17023SJohn Marino ordering, as on the ARM. */
132*e4b17023SJohn Marino
133*e4b17023SJohn Marino const struct floatformat floatformat_ieee_double_littlebyte_bigword =
134*e4b17023SJohn Marino {
135*e4b17023SJohn Marino floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52,
136*e4b17023SJohn Marino floatformat_intbit_no,
137*e4b17023SJohn Marino "floatformat_ieee_double_littlebyte_bigword",
138*e4b17023SJohn Marino floatformat_always_valid,
139*e4b17023SJohn Marino NULL
140*e4b17023SJohn Marino };
141*e4b17023SJohn Marino
142*e4b17023SJohn Marino /* floatformat for VAX. Not quite IEEE, but close enough. */
143*e4b17023SJohn Marino
144*e4b17023SJohn Marino const struct floatformat floatformat_vax_f =
145*e4b17023SJohn Marino {
146*e4b17023SJohn Marino floatformat_vax, 32, 0, 1, 8, 129, 0, 9, 23,
147*e4b17023SJohn Marino floatformat_intbit_no,
148*e4b17023SJohn Marino "floatformat_vax_f",
149*e4b17023SJohn Marino floatformat_always_valid,
150*e4b17023SJohn Marino NULL
151*e4b17023SJohn Marino };
152*e4b17023SJohn Marino const struct floatformat floatformat_vax_d =
153*e4b17023SJohn Marino {
154*e4b17023SJohn Marino floatformat_vax, 64, 0, 1, 8, 129, 0, 9, 55,
155*e4b17023SJohn Marino floatformat_intbit_no,
156*e4b17023SJohn Marino "floatformat_vax_d",
157*e4b17023SJohn Marino floatformat_always_valid,
158*e4b17023SJohn Marino NULL
159*e4b17023SJohn Marino };
160*e4b17023SJohn Marino const struct floatformat floatformat_vax_g =
161*e4b17023SJohn Marino {
162*e4b17023SJohn Marino floatformat_vax, 64, 0, 1, 11, 1025, 0, 12, 52,
163*e4b17023SJohn Marino floatformat_intbit_no,
164*e4b17023SJohn Marino "floatformat_vax_g",
165*e4b17023SJohn Marino floatformat_always_valid,
166*e4b17023SJohn Marino NULL
167*e4b17023SJohn Marino };
168*e4b17023SJohn Marino
169*e4b17023SJohn Marino static int floatformat_i387_ext_is_valid (const struct floatformat *fmt,
170*e4b17023SJohn Marino const void *from);
171*e4b17023SJohn Marino
172*e4b17023SJohn Marino static int
floatformat_i387_ext_is_valid(const struct floatformat * fmt,const void * from)173*e4b17023SJohn Marino floatformat_i387_ext_is_valid (const struct floatformat *fmt, const void *from)
174*e4b17023SJohn Marino {
175*e4b17023SJohn Marino /* In the i387 double-extended format, if the exponent is all ones,
176*e4b17023SJohn Marino then the integer bit must be set. If the exponent is neither 0
177*e4b17023SJohn Marino nor ~0, the intbit must also be set. Only if the exponent is
178*e4b17023SJohn Marino zero can it be zero, and then it must be zero. */
179*e4b17023SJohn Marino unsigned long exponent, int_bit;
180*e4b17023SJohn Marino const unsigned char *ufrom = (const unsigned char *) from;
181*e4b17023SJohn Marino
182*e4b17023SJohn Marino exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
183*e4b17023SJohn Marino fmt->exp_start, fmt->exp_len);
184*e4b17023SJohn Marino int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize,
185*e4b17023SJohn Marino fmt->man_start, 1);
186*e4b17023SJohn Marino
187*e4b17023SJohn Marino if ((exponent == 0) != (int_bit == 0))
188*e4b17023SJohn Marino return 0;
189*e4b17023SJohn Marino else
190*e4b17023SJohn Marino return 1;
191*e4b17023SJohn Marino }
192*e4b17023SJohn Marino
193*e4b17023SJohn Marino const struct floatformat floatformat_i387_ext =
194*e4b17023SJohn Marino {
195*e4b17023SJohn Marino floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
196*e4b17023SJohn Marino floatformat_intbit_yes,
197*e4b17023SJohn Marino "floatformat_i387_ext",
198*e4b17023SJohn Marino floatformat_i387_ext_is_valid,
199*e4b17023SJohn Marino NULL
200*e4b17023SJohn Marino };
201*e4b17023SJohn Marino const struct floatformat floatformat_m68881_ext =
202*e4b17023SJohn Marino {
203*e4b17023SJohn Marino /* Note that the bits from 16 to 31 are unused. */
204*e4b17023SJohn Marino floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64,
205*e4b17023SJohn Marino floatformat_intbit_yes,
206*e4b17023SJohn Marino "floatformat_m68881_ext",
207*e4b17023SJohn Marino floatformat_always_valid,
208*e4b17023SJohn Marino NULL
209*e4b17023SJohn Marino };
210*e4b17023SJohn Marino const struct floatformat floatformat_i960_ext =
211*e4b17023SJohn Marino {
212*e4b17023SJohn Marino /* Note that the bits from 0 to 15 are unused. */
213*e4b17023SJohn Marino floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64,
214*e4b17023SJohn Marino floatformat_intbit_yes,
215*e4b17023SJohn Marino "floatformat_i960_ext",
216*e4b17023SJohn Marino floatformat_always_valid,
217*e4b17023SJohn Marino NULL
218*e4b17023SJohn Marino };
219*e4b17023SJohn Marino const struct floatformat floatformat_m88110_ext =
220*e4b17023SJohn Marino {
221*e4b17023SJohn Marino floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64,
222*e4b17023SJohn Marino floatformat_intbit_yes,
223*e4b17023SJohn Marino "floatformat_m88110_ext",
224*e4b17023SJohn Marino floatformat_always_valid,
225*e4b17023SJohn Marino NULL
226*e4b17023SJohn Marino };
227*e4b17023SJohn Marino const struct floatformat floatformat_m88110_harris_ext =
228*e4b17023SJohn Marino {
229*e4b17023SJohn Marino /* Harris uses raw format 128 bytes long, but the number is just an ieee
230*e4b17023SJohn Marino double, and the last 64 bits are wasted. */
231*e4b17023SJohn Marino floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52,
232*e4b17023SJohn Marino floatformat_intbit_no,
233*e4b17023SJohn Marino "floatformat_m88110_ext_harris",
234*e4b17023SJohn Marino floatformat_always_valid,
235*e4b17023SJohn Marino NULL
236*e4b17023SJohn Marino };
237*e4b17023SJohn Marino const struct floatformat floatformat_arm_ext_big =
238*e4b17023SJohn Marino {
239*e4b17023SJohn Marino /* Bits 1 to 16 are unused. */
240*e4b17023SJohn Marino floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
241*e4b17023SJohn Marino floatformat_intbit_yes,
242*e4b17023SJohn Marino "floatformat_arm_ext_big",
243*e4b17023SJohn Marino floatformat_always_valid,
244*e4b17023SJohn Marino NULL
245*e4b17023SJohn Marino };
246*e4b17023SJohn Marino const struct floatformat floatformat_arm_ext_littlebyte_bigword =
247*e4b17023SJohn Marino {
248*e4b17023SJohn Marino /* Bits 1 to 16 are unused. */
249*e4b17023SJohn Marino floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64,
250*e4b17023SJohn Marino floatformat_intbit_yes,
251*e4b17023SJohn Marino "floatformat_arm_ext_littlebyte_bigword",
252*e4b17023SJohn Marino floatformat_always_valid,
253*e4b17023SJohn Marino NULL
254*e4b17023SJohn Marino };
255*e4b17023SJohn Marino const struct floatformat floatformat_ia64_spill_big =
256*e4b17023SJohn Marino {
257*e4b17023SJohn Marino floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
258*e4b17023SJohn Marino floatformat_intbit_yes,
259*e4b17023SJohn Marino "floatformat_ia64_spill_big",
260*e4b17023SJohn Marino floatformat_always_valid,
261*e4b17023SJohn Marino NULL
262*e4b17023SJohn Marino };
263*e4b17023SJohn Marino const struct floatformat floatformat_ia64_spill_little =
264*e4b17023SJohn Marino {
265*e4b17023SJohn Marino floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64,
266*e4b17023SJohn Marino floatformat_intbit_yes,
267*e4b17023SJohn Marino "floatformat_ia64_spill_little",
268*e4b17023SJohn Marino floatformat_always_valid,
269*e4b17023SJohn Marino NULL
270*e4b17023SJohn Marino };
271*e4b17023SJohn Marino const struct floatformat floatformat_ia64_quad_big =
272*e4b17023SJohn Marino {
273*e4b17023SJohn Marino floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
274*e4b17023SJohn Marino floatformat_intbit_no,
275*e4b17023SJohn Marino "floatformat_ia64_quad_big",
276*e4b17023SJohn Marino floatformat_always_valid,
277*e4b17023SJohn Marino NULL
278*e4b17023SJohn Marino };
279*e4b17023SJohn Marino const struct floatformat floatformat_ia64_quad_little =
280*e4b17023SJohn Marino {
281*e4b17023SJohn Marino floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112,
282*e4b17023SJohn Marino floatformat_intbit_no,
283*e4b17023SJohn Marino "floatformat_ia64_quad_little",
284*e4b17023SJohn Marino floatformat_always_valid,
285*e4b17023SJohn Marino NULL
286*e4b17023SJohn Marino };
287*e4b17023SJohn Marino
288*e4b17023SJohn Marino static int
floatformat_ibm_long_double_is_valid(const struct floatformat * fmt,const void * from)289*e4b17023SJohn Marino floatformat_ibm_long_double_is_valid (const struct floatformat *fmt,
290*e4b17023SJohn Marino const void *from)
291*e4b17023SJohn Marino {
292*e4b17023SJohn Marino const unsigned char *ufrom = (const unsigned char *) from;
293*e4b17023SJohn Marino const struct floatformat *hfmt = fmt->split_half;
294*e4b17023SJohn Marino long top_exp, bot_exp;
295*e4b17023SJohn Marino int top_nan = 0;
296*e4b17023SJohn Marino
297*e4b17023SJohn Marino top_exp = get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
298*e4b17023SJohn Marino hfmt->exp_start, hfmt->exp_len);
299*e4b17023SJohn Marino bot_exp = get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
300*e4b17023SJohn Marino hfmt->exp_start, hfmt->exp_len);
301*e4b17023SJohn Marino
302*e4b17023SJohn Marino if ((unsigned long) top_exp == hfmt->exp_nan)
303*e4b17023SJohn Marino top_nan = mant_bits_set (hfmt, ufrom);
304*e4b17023SJohn Marino
305*e4b17023SJohn Marino /* A NaN is valid with any low part. */
306*e4b17023SJohn Marino if (top_nan)
307*e4b17023SJohn Marino return 1;
308*e4b17023SJohn Marino
309*e4b17023SJohn Marino /* An infinity, zero or denormal requires low part 0 (positive or
310*e4b17023SJohn Marino negative). */
311*e4b17023SJohn Marino if ((unsigned long) top_exp == hfmt->exp_nan || top_exp == 0)
312*e4b17023SJohn Marino {
313*e4b17023SJohn Marino if (bot_exp != 0)
314*e4b17023SJohn Marino return 0;
315*e4b17023SJohn Marino
316*e4b17023SJohn Marino return !mant_bits_set (hfmt, ufrom + 8);
317*e4b17023SJohn Marino }
318*e4b17023SJohn Marino
319*e4b17023SJohn Marino /* The top part is now a finite normal value. The long double value
320*e4b17023SJohn Marino is the sum of the two parts, and the top part must equal the
321*e4b17023SJohn Marino result of rounding the long double value to nearest double. Thus
322*e4b17023SJohn Marino the bottom part must be <= 0.5ulp of the top part in absolute
323*e4b17023SJohn Marino value, and if it is < 0.5ulp then the long double is definitely
324*e4b17023SJohn Marino valid. */
325*e4b17023SJohn Marino if (bot_exp < top_exp - 53)
326*e4b17023SJohn Marino return 1;
327*e4b17023SJohn Marino if (bot_exp > top_exp - 53 && bot_exp != 0)
328*e4b17023SJohn Marino return 0;
329*e4b17023SJohn Marino if (bot_exp == 0)
330*e4b17023SJohn Marino {
331*e4b17023SJohn Marino /* The bottom part is 0 or denormal. Determine which, and if
332*e4b17023SJohn Marino denormal the first two set bits. */
333*e4b17023SJohn Marino int first_bit = -1, second_bit = -1, cur_bit;
334*e4b17023SJohn Marino for (cur_bit = 0; (unsigned int) cur_bit < hfmt->man_len; cur_bit++)
335*e4b17023SJohn Marino if (get_field (ufrom + 8, hfmt->byteorder, hfmt->totalsize,
336*e4b17023SJohn Marino hfmt->man_start + cur_bit, 1))
337*e4b17023SJohn Marino {
338*e4b17023SJohn Marino if (first_bit == -1)
339*e4b17023SJohn Marino first_bit = cur_bit;
340*e4b17023SJohn Marino else
341*e4b17023SJohn Marino {
342*e4b17023SJohn Marino second_bit = cur_bit;
343*e4b17023SJohn Marino break;
344*e4b17023SJohn Marino }
345*e4b17023SJohn Marino }
346*e4b17023SJohn Marino /* Bottom part 0 is OK. */
347*e4b17023SJohn Marino if (first_bit == -1)
348*e4b17023SJohn Marino return 1;
349*e4b17023SJohn Marino /* The real exponent of the bottom part is -first_bit. */
350*e4b17023SJohn Marino if (-first_bit < top_exp - 53)
351*e4b17023SJohn Marino return 1;
352*e4b17023SJohn Marino if (-first_bit > top_exp - 53)
353*e4b17023SJohn Marino return 0;
354*e4b17023SJohn Marino /* The bottom part is at least 0.5ulp of the top part. For this
355*e4b17023SJohn Marino to be OK, the bottom part must be exactly 0.5ulp (i.e. no
356*e4b17023SJohn Marino more bits set) and the top part must have last bit 0. */
357*e4b17023SJohn Marino if (second_bit != -1)
358*e4b17023SJohn Marino return 0;
359*e4b17023SJohn Marino return !get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
360*e4b17023SJohn Marino hfmt->man_start + hfmt->man_len - 1, 1);
361*e4b17023SJohn Marino }
362*e4b17023SJohn Marino else
363*e4b17023SJohn Marino {
364*e4b17023SJohn Marino /* The bottom part is at least 0.5ulp of the top part. For this
365*e4b17023SJohn Marino to be OK, it must be exactly 0.5ulp (i.e. no explicit bits
366*e4b17023SJohn Marino set) and the top part must have last bit 0. */
367*e4b17023SJohn Marino if (get_field (ufrom, hfmt->byteorder, hfmt->totalsize,
368*e4b17023SJohn Marino hfmt->man_start + hfmt->man_len - 1, 1))
369*e4b17023SJohn Marino return 0;
370*e4b17023SJohn Marino return !mant_bits_set (hfmt, ufrom + 8);
371*e4b17023SJohn Marino }
372*e4b17023SJohn Marino }
373*e4b17023SJohn Marino
374*e4b17023SJohn Marino const struct floatformat floatformat_ibm_long_double =
375*e4b17023SJohn Marino {
376*e4b17023SJohn Marino floatformat_big, 128, 0, 1, 11, 1023, 2047, 12, 52,
377*e4b17023SJohn Marino floatformat_intbit_no,
378*e4b17023SJohn Marino "floatformat_ibm_long_double",
379*e4b17023SJohn Marino floatformat_ibm_long_double_is_valid,
380*e4b17023SJohn Marino &floatformat_ieee_double_big
381*e4b17023SJohn Marino };
382*e4b17023SJohn Marino
383*e4b17023SJohn Marino
384*e4b17023SJohn Marino #ifndef min
385*e4b17023SJohn Marino #define min(a, b) ((a) < (b) ? (a) : (b))
386*e4b17023SJohn Marino #endif
387*e4b17023SJohn Marino
388*e4b17023SJohn Marino /* Return 1 if any bits are explicitly set in the mantissa of UFROM,
389*e4b17023SJohn Marino format FMT, 0 otherwise. */
390*e4b17023SJohn Marino static int
mant_bits_set(const struct floatformat * fmt,const unsigned char * ufrom)391*e4b17023SJohn Marino mant_bits_set (const struct floatformat *fmt, const unsigned char *ufrom)
392*e4b17023SJohn Marino {
393*e4b17023SJohn Marino unsigned int mant_bits, mant_off;
394*e4b17023SJohn Marino int mant_bits_left;
395*e4b17023SJohn Marino
396*e4b17023SJohn Marino mant_off = fmt->man_start;
397*e4b17023SJohn Marino mant_bits_left = fmt->man_len;
398*e4b17023SJohn Marino while (mant_bits_left > 0)
399*e4b17023SJohn Marino {
400*e4b17023SJohn Marino mant_bits = min (mant_bits_left, 32);
401*e4b17023SJohn Marino
402*e4b17023SJohn Marino if (get_field (ufrom, fmt->byteorder, fmt->totalsize,
403*e4b17023SJohn Marino mant_off, mant_bits) != 0)
404*e4b17023SJohn Marino return 1;
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino mant_off += mant_bits;
407*e4b17023SJohn Marino mant_bits_left -= mant_bits;
408*e4b17023SJohn Marino }
409*e4b17023SJohn Marino return 0;
410*e4b17023SJohn Marino }
411*e4b17023SJohn Marino
412*e4b17023SJohn Marino /* Extract a field which starts at START and is LEN bits long. DATA and
413*e4b17023SJohn Marino TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
414*e4b17023SJohn Marino static unsigned long
get_field(const unsigned char * data,enum floatformat_byteorders order,unsigned int total_len,unsigned int start,unsigned int len)415*e4b17023SJohn Marino get_field (const unsigned char *data, enum floatformat_byteorders order,
416*e4b17023SJohn Marino unsigned int total_len, unsigned int start, unsigned int len)
417*e4b17023SJohn Marino {
418*e4b17023SJohn Marino unsigned long result = 0;
419*e4b17023SJohn Marino unsigned int cur_byte;
420*e4b17023SJohn Marino int lo_bit, hi_bit, cur_bitshift = 0;
421*e4b17023SJohn Marino int nextbyte = (order == floatformat_little) ? 1 : -1;
422*e4b17023SJohn Marino
423*e4b17023SJohn Marino /* Start is in big-endian bit order! Fix that first. */
424*e4b17023SJohn Marino start = total_len - (start + len);
425*e4b17023SJohn Marino
426*e4b17023SJohn Marino /* Start at the least significant part of the field. */
427*e4b17023SJohn Marino if (order == floatformat_little)
428*e4b17023SJohn Marino cur_byte = start / FLOATFORMAT_CHAR_BIT;
429*e4b17023SJohn Marino else
430*e4b17023SJohn Marino cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
431*e4b17023SJohn Marino
432*e4b17023SJohn Marino lo_bit = start % FLOATFORMAT_CHAR_BIT;
433*e4b17023SJohn Marino hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
434*e4b17023SJohn Marino
435*e4b17023SJohn Marino do
436*e4b17023SJohn Marino {
437*e4b17023SJohn Marino unsigned int shifted = *(data + cur_byte) >> lo_bit;
438*e4b17023SJohn Marino unsigned int bits = hi_bit - lo_bit;
439*e4b17023SJohn Marino unsigned int mask = (1 << bits) - 1;
440*e4b17023SJohn Marino result |= (shifted & mask) << cur_bitshift;
441*e4b17023SJohn Marino len -= bits;
442*e4b17023SJohn Marino cur_bitshift += bits;
443*e4b17023SJohn Marino cur_byte += nextbyte;
444*e4b17023SJohn Marino lo_bit = 0;
445*e4b17023SJohn Marino hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
446*e4b17023SJohn Marino }
447*e4b17023SJohn Marino while (len != 0);
448*e4b17023SJohn Marino
449*e4b17023SJohn Marino return result;
450*e4b17023SJohn Marino }
451*e4b17023SJohn Marino
452*e4b17023SJohn Marino /* Convert from FMT to a double.
453*e4b17023SJohn Marino FROM is the address of the extended float.
454*e4b17023SJohn Marino Store the double in *TO. */
455*e4b17023SJohn Marino
456*e4b17023SJohn Marino void
floatformat_to_double(const struct floatformat * fmt,const void * from,double * to)457*e4b17023SJohn Marino floatformat_to_double (const struct floatformat *fmt,
458*e4b17023SJohn Marino const void *from, double *to)
459*e4b17023SJohn Marino {
460*e4b17023SJohn Marino const unsigned char *ufrom = (const unsigned char *) from;
461*e4b17023SJohn Marino double dto;
462*e4b17023SJohn Marino long exponent;
463*e4b17023SJohn Marino unsigned long mant;
464*e4b17023SJohn Marino unsigned int mant_bits, mant_off;
465*e4b17023SJohn Marino int mant_bits_left;
466*e4b17023SJohn Marino int special_exponent; /* It's a NaN, denorm or zero */
467*e4b17023SJohn Marino
468*e4b17023SJohn Marino /* Split values are not handled specially, since the top half has
469*e4b17023SJohn Marino the correctly rounded double value (in the only supported case of
470*e4b17023SJohn Marino split values). */
471*e4b17023SJohn Marino
472*e4b17023SJohn Marino exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize,
473*e4b17023SJohn Marino fmt->exp_start, fmt->exp_len);
474*e4b17023SJohn Marino
475*e4b17023SJohn Marino /* If the exponent indicates a NaN, we don't have information to
476*e4b17023SJohn Marino decide what to do. So we handle it like IEEE, except that we
477*e4b17023SJohn Marino don't try to preserve the type of NaN. FIXME. */
478*e4b17023SJohn Marino if ((unsigned long) exponent == fmt->exp_nan)
479*e4b17023SJohn Marino {
480*e4b17023SJohn Marino int nan = mant_bits_set (fmt, ufrom);
481*e4b17023SJohn Marino
482*e4b17023SJohn Marino /* On certain systems (such as GNU/Linux), the use of the
483*e4b17023SJohn Marino INFINITY macro below may generate a warning that can not be
484*e4b17023SJohn Marino silenced due to a bug in GCC (PR preprocessor/11931). The
485*e4b17023SJohn Marino preprocessor fails to recognise the __extension__ keyword in
486*e4b17023SJohn Marino conjunction with the GNU/C99 extension for hexadecimal
487*e4b17023SJohn Marino floating point constants and will issue a warning when
488*e4b17023SJohn Marino compiling with -pedantic. */
489*e4b17023SJohn Marino if (nan)
490*e4b17023SJohn Marino dto = NAN;
491*e4b17023SJohn Marino else
492*e4b17023SJohn Marino dto = INFINITY;
493*e4b17023SJohn Marino
494*e4b17023SJohn Marino if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
495*e4b17023SJohn Marino dto = -dto;
496*e4b17023SJohn Marino
497*e4b17023SJohn Marino *to = dto;
498*e4b17023SJohn Marino
499*e4b17023SJohn Marino return;
500*e4b17023SJohn Marino }
501*e4b17023SJohn Marino
502*e4b17023SJohn Marino mant_bits_left = fmt->man_len;
503*e4b17023SJohn Marino mant_off = fmt->man_start;
504*e4b17023SJohn Marino dto = 0.0;
505*e4b17023SJohn Marino
506*e4b17023SJohn Marino special_exponent = exponent == 0 || (unsigned long) exponent == fmt->exp_nan;
507*e4b17023SJohn Marino
508*e4b17023SJohn Marino /* Don't bias zero's, denorms or NaNs. */
509*e4b17023SJohn Marino if (!special_exponent)
510*e4b17023SJohn Marino exponent -= fmt->exp_bias;
511*e4b17023SJohn Marino
512*e4b17023SJohn Marino /* Build the result algebraically. Might go infinite, underflow, etc;
513*e4b17023SJohn Marino who cares. */
514*e4b17023SJohn Marino
515*e4b17023SJohn Marino /* If this format uses a hidden bit, explicitly add it in now. Otherwise,
516*e4b17023SJohn Marino increment the exponent by one to account for the integer bit. */
517*e4b17023SJohn Marino
518*e4b17023SJohn Marino if (!special_exponent)
519*e4b17023SJohn Marino {
520*e4b17023SJohn Marino if (fmt->intbit == floatformat_intbit_no)
521*e4b17023SJohn Marino dto = ldexp (1.0, exponent);
522*e4b17023SJohn Marino else
523*e4b17023SJohn Marino exponent++;
524*e4b17023SJohn Marino }
525*e4b17023SJohn Marino
526*e4b17023SJohn Marino while (mant_bits_left > 0)
527*e4b17023SJohn Marino {
528*e4b17023SJohn Marino mant_bits = min (mant_bits_left, 32);
529*e4b17023SJohn Marino
530*e4b17023SJohn Marino mant = get_field (ufrom, fmt->byteorder, fmt->totalsize,
531*e4b17023SJohn Marino mant_off, mant_bits);
532*e4b17023SJohn Marino
533*e4b17023SJohn Marino /* Handle denormalized numbers. FIXME: What should we do for
534*e4b17023SJohn Marino non-IEEE formats? */
535*e4b17023SJohn Marino if (special_exponent && exponent == 0 && mant != 0)
536*e4b17023SJohn Marino dto += ldexp ((double)mant,
537*e4b17023SJohn Marino (- fmt->exp_bias
538*e4b17023SJohn Marino - mant_bits
539*e4b17023SJohn Marino - (mant_off - fmt->man_start)
540*e4b17023SJohn Marino + 1));
541*e4b17023SJohn Marino else
542*e4b17023SJohn Marino dto += ldexp ((double)mant, exponent - mant_bits);
543*e4b17023SJohn Marino if (exponent != 0)
544*e4b17023SJohn Marino exponent -= mant_bits;
545*e4b17023SJohn Marino mant_off += mant_bits;
546*e4b17023SJohn Marino mant_bits_left -= mant_bits;
547*e4b17023SJohn Marino }
548*e4b17023SJohn Marino
549*e4b17023SJohn Marino /* Negate it if negative. */
550*e4b17023SJohn Marino if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1))
551*e4b17023SJohn Marino dto = -dto;
552*e4b17023SJohn Marino *to = dto;
553*e4b17023SJohn Marino }
554*e4b17023SJohn Marino
555*e4b17023SJohn Marino static void put_field (unsigned char *, enum floatformat_byteorders,
556*e4b17023SJohn Marino unsigned int,
557*e4b17023SJohn Marino unsigned int,
558*e4b17023SJohn Marino unsigned int,
559*e4b17023SJohn Marino unsigned long);
560*e4b17023SJohn Marino
561*e4b17023SJohn Marino /* Set a field which starts at START and is LEN bits long. DATA and
562*e4b17023SJohn Marino TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */
563*e4b17023SJohn Marino static void
put_field(unsigned char * data,enum floatformat_byteorders order,unsigned int total_len,unsigned int start,unsigned int len,unsigned long stuff_to_put)564*e4b17023SJohn Marino put_field (unsigned char *data, enum floatformat_byteorders order,
565*e4b17023SJohn Marino unsigned int total_len, unsigned int start, unsigned int len,
566*e4b17023SJohn Marino unsigned long stuff_to_put)
567*e4b17023SJohn Marino {
568*e4b17023SJohn Marino unsigned int cur_byte;
569*e4b17023SJohn Marino int lo_bit, hi_bit;
570*e4b17023SJohn Marino int nextbyte = (order == floatformat_little) ? 1 : -1;
571*e4b17023SJohn Marino
572*e4b17023SJohn Marino /* Start is in big-endian bit order! Fix that first. */
573*e4b17023SJohn Marino start = total_len - (start + len);
574*e4b17023SJohn Marino
575*e4b17023SJohn Marino /* Start at the least significant part of the field. */
576*e4b17023SJohn Marino if (order == floatformat_little)
577*e4b17023SJohn Marino cur_byte = start / FLOATFORMAT_CHAR_BIT;
578*e4b17023SJohn Marino else
579*e4b17023SJohn Marino cur_byte = (total_len - start - 1) / FLOATFORMAT_CHAR_BIT;
580*e4b17023SJohn Marino
581*e4b17023SJohn Marino lo_bit = start % FLOATFORMAT_CHAR_BIT;
582*e4b17023SJohn Marino hi_bit = min (lo_bit + len, FLOATFORMAT_CHAR_BIT);
583*e4b17023SJohn Marino
584*e4b17023SJohn Marino do
585*e4b17023SJohn Marino {
586*e4b17023SJohn Marino unsigned char *byte_ptr = data + cur_byte;
587*e4b17023SJohn Marino unsigned int bits = hi_bit - lo_bit;
588*e4b17023SJohn Marino unsigned int mask = ((1 << bits) - 1) << lo_bit;
589*e4b17023SJohn Marino *byte_ptr = (*byte_ptr & ~mask) | ((stuff_to_put << lo_bit) & mask);
590*e4b17023SJohn Marino stuff_to_put >>= bits;
591*e4b17023SJohn Marino len -= bits;
592*e4b17023SJohn Marino cur_byte += nextbyte;
593*e4b17023SJohn Marino lo_bit = 0;
594*e4b17023SJohn Marino hi_bit = min (len, FLOATFORMAT_CHAR_BIT);
595*e4b17023SJohn Marino }
596*e4b17023SJohn Marino while (len != 0);
597*e4b17023SJohn Marino }
598*e4b17023SJohn Marino
599*e4b17023SJohn Marino /* The converse: convert the double *FROM to an extended float
600*e4b17023SJohn Marino and store where TO points. Neither FROM nor TO have any alignment
601*e4b17023SJohn Marino restrictions. */
602*e4b17023SJohn Marino
603*e4b17023SJohn Marino void
floatformat_from_double(const struct floatformat * fmt,const double * from,void * to)604*e4b17023SJohn Marino floatformat_from_double (const struct floatformat *fmt,
605*e4b17023SJohn Marino const double *from, void *to)
606*e4b17023SJohn Marino {
607*e4b17023SJohn Marino double dfrom;
608*e4b17023SJohn Marino int exponent;
609*e4b17023SJohn Marino double mant;
610*e4b17023SJohn Marino unsigned int mant_bits, mant_off;
611*e4b17023SJohn Marino int mant_bits_left;
612*e4b17023SJohn Marino unsigned char *uto = (unsigned char *) to;
613*e4b17023SJohn Marino
614*e4b17023SJohn Marino dfrom = *from;
615*e4b17023SJohn Marino memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT);
616*e4b17023SJohn Marino
617*e4b17023SJohn Marino /* Split values are not handled specially, since a bottom half of
618*e4b17023SJohn Marino zero is correct for any value representable as double (in the
619*e4b17023SJohn Marino only supported case of split values). */
620*e4b17023SJohn Marino
621*e4b17023SJohn Marino /* If negative, set the sign bit. */
622*e4b17023SJohn Marino if (dfrom < 0)
623*e4b17023SJohn Marino {
624*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1);
625*e4b17023SJohn Marino dfrom = -dfrom;
626*e4b17023SJohn Marino }
627*e4b17023SJohn Marino
628*e4b17023SJohn Marino if (dfrom == 0)
629*e4b17023SJohn Marino {
630*e4b17023SJohn Marino /* 0.0. */
631*e4b17023SJohn Marino return;
632*e4b17023SJohn Marino }
633*e4b17023SJohn Marino
634*e4b17023SJohn Marino if (dfrom != dfrom)
635*e4b17023SJohn Marino {
636*e4b17023SJohn Marino /* NaN. */
637*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
638*e4b17023SJohn Marino fmt->exp_len, fmt->exp_nan);
639*e4b17023SJohn Marino /* Be sure it's not infinity, but NaN value is irrelevant. */
640*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start,
641*e4b17023SJohn Marino 32, 1);
642*e4b17023SJohn Marino return;
643*e4b17023SJohn Marino }
644*e4b17023SJohn Marino
645*e4b17023SJohn Marino if (dfrom + dfrom == dfrom)
646*e4b17023SJohn Marino {
647*e4b17023SJohn Marino /* This can only happen for an infinite value (or zero, which we
648*e4b17023SJohn Marino already handled above). */
649*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
650*e4b17023SJohn Marino fmt->exp_len, fmt->exp_nan);
651*e4b17023SJohn Marino return;
652*e4b17023SJohn Marino }
653*e4b17023SJohn Marino
654*e4b17023SJohn Marino mant = frexp (dfrom, &exponent);
655*e4b17023SJohn Marino if (exponent + fmt->exp_bias - 1 > 0)
656*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
657*e4b17023SJohn Marino fmt->exp_len, exponent + fmt->exp_bias - 1);
658*e4b17023SJohn Marino else
659*e4b17023SJohn Marino {
660*e4b17023SJohn Marino /* Handle a denormalized number. FIXME: What should we do for
661*e4b17023SJohn Marino non-IEEE formats? */
662*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start,
663*e4b17023SJohn Marino fmt->exp_len, 0);
664*e4b17023SJohn Marino mant = ldexp (mant, exponent + fmt->exp_bias - 1);
665*e4b17023SJohn Marino }
666*e4b17023SJohn Marino
667*e4b17023SJohn Marino mant_bits_left = fmt->man_len;
668*e4b17023SJohn Marino mant_off = fmt->man_start;
669*e4b17023SJohn Marino while (mant_bits_left > 0)
670*e4b17023SJohn Marino {
671*e4b17023SJohn Marino unsigned long mant_long;
672*e4b17023SJohn Marino mant_bits = mant_bits_left < 32 ? mant_bits_left : 32;
673*e4b17023SJohn Marino
674*e4b17023SJohn Marino mant *= 4294967296.0;
675*e4b17023SJohn Marino mant_long = (unsigned long)mant;
676*e4b17023SJohn Marino mant -= mant_long;
677*e4b17023SJohn Marino
678*e4b17023SJohn Marino /* If the integer bit is implicit, and we are not creating a
679*e4b17023SJohn Marino denormalized number, then we need to discard it. */
680*e4b17023SJohn Marino if ((unsigned int) mant_bits_left == fmt->man_len
681*e4b17023SJohn Marino && fmt->intbit == floatformat_intbit_no
682*e4b17023SJohn Marino && exponent + fmt->exp_bias - 1 > 0)
683*e4b17023SJohn Marino {
684*e4b17023SJohn Marino mant_long &= 0x7fffffff;
685*e4b17023SJohn Marino mant_bits -= 1;
686*e4b17023SJohn Marino }
687*e4b17023SJohn Marino else if (mant_bits < 32)
688*e4b17023SJohn Marino {
689*e4b17023SJohn Marino /* The bits we want are in the most significant MANT_BITS bits of
690*e4b17023SJohn Marino mant_long. Move them to the least significant. */
691*e4b17023SJohn Marino mant_long >>= 32 - mant_bits;
692*e4b17023SJohn Marino }
693*e4b17023SJohn Marino
694*e4b17023SJohn Marino put_field (uto, fmt->byteorder, fmt->totalsize,
695*e4b17023SJohn Marino mant_off, mant_bits, mant_long);
696*e4b17023SJohn Marino mant_off += mant_bits;
697*e4b17023SJohn Marino mant_bits_left -= mant_bits;
698*e4b17023SJohn Marino }
699*e4b17023SJohn Marino }
700*e4b17023SJohn Marino
701*e4b17023SJohn Marino /* Return non-zero iff the data at FROM is a valid number in format FMT. */
702*e4b17023SJohn Marino
703*e4b17023SJohn Marino int
floatformat_is_valid(const struct floatformat * fmt,const void * from)704*e4b17023SJohn Marino floatformat_is_valid (const struct floatformat *fmt, const void *from)
705*e4b17023SJohn Marino {
706*e4b17023SJohn Marino return fmt->is_valid (fmt, from);
707*e4b17023SJohn Marino }
708*e4b17023SJohn Marino
709*e4b17023SJohn Marino
710*e4b17023SJohn Marino #ifdef IEEE_DEBUG
711*e4b17023SJohn Marino
712*e4b17023SJohn Marino #include <stdio.h>
713*e4b17023SJohn Marino
714*e4b17023SJohn Marino /* This is to be run on a host which uses IEEE floating point. */
715*e4b17023SJohn Marino
716*e4b17023SJohn Marino void
ieee_test(double n)717*e4b17023SJohn Marino ieee_test (double n)
718*e4b17023SJohn Marino {
719*e4b17023SJohn Marino double result;
720*e4b17023SJohn Marino
721*e4b17023SJohn Marino floatformat_to_double (&floatformat_ieee_double_little, &n, &result);
722*e4b17023SJohn Marino if ((n != result && (! isnan (n) || ! isnan (result)))
723*e4b17023SJohn Marino || (n < 0 && result >= 0)
724*e4b17023SJohn Marino || (n >= 0 && result < 0))
725*e4b17023SJohn Marino printf ("Differ(to): %.20g -> %.20g\n", n, result);
726*e4b17023SJohn Marino
727*e4b17023SJohn Marino floatformat_from_double (&floatformat_ieee_double_little, &n, &result);
728*e4b17023SJohn Marino if ((n != result && (! isnan (n) || ! isnan (result)))
729*e4b17023SJohn Marino || (n < 0 && result >= 0)
730*e4b17023SJohn Marino || (n >= 0 && result < 0))
731*e4b17023SJohn Marino printf ("Differ(from): %.20g -> %.20g\n", n, result);
732*e4b17023SJohn Marino
733*e4b17023SJohn Marino #if 0
734*e4b17023SJohn Marino {
735*e4b17023SJohn Marino char exten[16];
736*e4b17023SJohn Marino
737*e4b17023SJohn Marino floatformat_from_double (&floatformat_m68881_ext, &n, exten);
738*e4b17023SJohn Marino floatformat_to_double (&floatformat_m68881_ext, exten, &result);
739*e4b17023SJohn Marino if (n != result)
740*e4b17023SJohn Marino printf ("Differ(to+from): %.20g -> %.20g\n", n, result);
741*e4b17023SJohn Marino }
742*e4b17023SJohn Marino #endif
743*e4b17023SJohn Marino
744*e4b17023SJohn Marino #if IEEE_DEBUG > 1
745*e4b17023SJohn Marino /* This is to be run on a host which uses 68881 format. */
746*e4b17023SJohn Marino {
747*e4b17023SJohn Marino long double ex = *(long double *)exten;
748*e4b17023SJohn Marino if (ex != n)
749*e4b17023SJohn Marino printf ("Differ(from vs. extended): %.20g\n", n);
750*e4b17023SJohn Marino }
751*e4b17023SJohn Marino #endif
752*e4b17023SJohn Marino }
753*e4b17023SJohn Marino
754*e4b17023SJohn Marino int
main(void)755*e4b17023SJohn Marino main (void)
756*e4b17023SJohn Marino {
757*e4b17023SJohn Marino ieee_test (0.0);
758*e4b17023SJohn Marino ieee_test (0.5);
759*e4b17023SJohn Marino ieee_test (256.0);
760*e4b17023SJohn Marino ieee_test (0.12345);
761*e4b17023SJohn Marino ieee_test (234235.78907234);
762*e4b17023SJohn Marino ieee_test (-512.0);
763*e4b17023SJohn Marino ieee_test (-0.004321);
764*e4b17023SJohn Marino ieee_test (1.2E-70);
765*e4b17023SJohn Marino ieee_test (1.2E-316);
766*e4b17023SJohn Marino ieee_test (4.9406564584124654E-324);
767*e4b17023SJohn Marino ieee_test (- 4.9406564584124654E-324);
768*e4b17023SJohn Marino ieee_test (- 0.0);
769*e4b17023SJohn Marino ieee_test (- INFINITY);
770*e4b17023SJohn Marino ieee_test (- NAN);
771*e4b17023SJohn Marino ieee_test (INFINITY);
772*e4b17023SJohn Marino ieee_test (NAN);
773*e4b17023SJohn Marino return 0;
774*e4b17023SJohn Marino }
775*e4b17023SJohn Marino #endif
776