1 |
/* IEEE floating point support routines, for GDB, the GNU Debugger. |
/* IEEE floating point support routines, for GDB, the GNU Debugger. |
2 |
Copyright (C) 1991, 1994, 1999, 2000 Free Software Foundation, Inc. |
Copyright (C) 1991, 1994, 1999, 2000, 2003 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GDB. |
This file is part of GDB. |
5 |
|
|
17 |
along with this program; if not, write to the Free Software |
along with this program; if not, write to the Free Software |
18 |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
19 |
|
|
20 |
|
/* This is needed to pick up the NAN macro on some systems. */ |
21 |
|
#define _GNU_SOURCE |
22 |
|
|
23 |
|
#ifdef HAVE_CONFIG_H |
24 |
|
#include "config.h" |
25 |
|
#endif |
26 |
|
|
27 |
|
#include <math.h> |
28 |
|
|
29 |
|
#ifdef HAVE_STRING_H |
30 |
|
#include <string.h> |
31 |
|
#endif |
32 |
|
|
33 |
|
#include "ansidecl.h" |
34 |
|
#include "libiberty.h" |
35 |
#include "floatformat.h" |
#include "floatformat.h" |
36 |
#include <math.h> /* ldexp */ |
|
37 |
#ifdef __STDC__ |
#ifndef INFINITY |
38 |
#include <stddef.h> |
#ifdef HUGE_VAL |
39 |
extern void *memcpy (void *s1, const void *s2, size_t n); |
#define INFINITY HUGE_VAL |
|
extern void *memset (void *s, int c, size_t n); |
|
40 |
#else |
#else |
41 |
extern char *memcpy (); |
#define INFINITY (1.0 / 0.0) |
42 |
extern char *memset (); |
#endif |
43 |
|
#endif |
44 |
|
|
45 |
|
#ifndef NAN |
46 |
|
#define NAN (0.0 / 0.0) |
47 |
#endif |
#endif |
48 |
|
|
49 |
|
static unsigned long get_field PARAMS ((const unsigned char *, |
50 |
|
enum floatformat_byteorders, |
51 |
|
unsigned int, |
52 |
|
unsigned int, |
53 |
|
unsigned int)); |
54 |
|
static int floatformat_always_valid PARAMS ((const struct floatformat *fmt, |
55 |
|
const char *from)); |
56 |
|
|
57 |
|
static int |
58 |
|
floatformat_always_valid (fmt, from) |
59 |
|
const struct floatformat *fmt ATTRIBUTE_UNUSED; |
60 |
|
const char *from ATTRIBUTE_UNUSED; |
61 |
|
{ |
62 |
|
return 1; |
63 |
|
} |
64 |
|
|
65 |
/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not |
/* The odds that CHAR_BIT will be anything but 8 are low enough that I'm not |
66 |
going to bother with trying to muck around with whether it is defined in |
going to bother with trying to muck around with whether it is defined in |
67 |
a system header, what we do if not, etc. */ |
a system header, what we do if not, etc. */ |
72 |
{ |
{ |
73 |
floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23, |
floatformat_big, 32, 0, 1, 8, 127, 255, 9, 23, |
74 |
floatformat_intbit_no, |
floatformat_intbit_no, |
75 |
"floatformat_ieee_single_big" |
"floatformat_ieee_single_big", |
76 |
|
floatformat_always_valid |
77 |
}; |
}; |
78 |
const struct floatformat floatformat_ieee_single_little = |
const struct floatformat floatformat_ieee_single_little = |
79 |
{ |
{ |
80 |
floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23, |
floatformat_little, 32, 0, 1, 8, 127, 255, 9, 23, |
81 |
floatformat_intbit_no, |
floatformat_intbit_no, |
82 |
"floatformat_ieee_single_little" |
"floatformat_ieee_single_little", |
83 |
|
floatformat_always_valid |
84 |
}; |
}; |
85 |
const struct floatformat floatformat_ieee_double_big = |
const struct floatformat floatformat_ieee_double_big = |
86 |
{ |
{ |
87 |
floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52, |
floatformat_big, 64, 0, 1, 11, 1023, 2047, 12, 52, |
88 |
floatformat_intbit_no, |
floatformat_intbit_no, |
89 |
"floatformat_ieee_double_big" |
"floatformat_ieee_double_big", |
90 |
|
floatformat_always_valid |
91 |
}; |
}; |
92 |
const struct floatformat floatformat_ieee_double_little = |
const struct floatformat floatformat_ieee_double_little = |
93 |
{ |
{ |
94 |
floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52, |
floatformat_little, 64, 0, 1, 11, 1023, 2047, 12, 52, |
95 |
floatformat_intbit_no, |
floatformat_intbit_no, |
96 |
"floatformat_ieee_double_little" |
"floatformat_ieee_double_little", |
97 |
|
floatformat_always_valid |
98 |
}; |
}; |
99 |
|
|
100 |
/* floatformat for IEEE double, little endian byte order, with big endian word |
/* floatformat for IEEE double, little endian byte order, with big endian word |
104 |
{ |
{ |
105 |
floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52, |
floatformat_littlebyte_bigword, 64, 0, 1, 11, 1023, 2047, 12, 52, |
106 |
floatformat_intbit_no, |
floatformat_intbit_no, |
107 |
"floatformat_ieee_double_little" |
"floatformat_ieee_double_littlebyte_bigword", |
108 |
|
floatformat_always_valid |
109 |
}; |
}; |
110 |
|
|
111 |
|
static int floatformat_i387_ext_is_valid PARAMS ((const struct floatformat *fmt, const char *from)); |
112 |
|
|
113 |
|
static int |
114 |
|
floatformat_i387_ext_is_valid (fmt, from) |
115 |
|
const struct floatformat *fmt; |
116 |
|
const char *from; |
117 |
|
{ |
118 |
|
/* In the i387 double-extended format, if the exponent is all ones, |
119 |
|
then the integer bit must be set. If the exponent is neither 0 |
120 |
|
nor ~0, the intbit must also be set. Only if the exponent is |
121 |
|
zero can it be zero, and then it must be zero. */ |
122 |
|
unsigned long exponent, int_bit; |
123 |
|
const unsigned char *ufrom = (const unsigned char *) from; |
124 |
|
|
125 |
|
exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, |
126 |
|
fmt->exp_start, fmt->exp_len); |
127 |
|
int_bit = get_field (ufrom, fmt->byteorder, fmt->totalsize, |
128 |
|
fmt->man_start, 1); |
129 |
|
|
130 |
|
if ((exponent == 0) != (int_bit == 0)) |
131 |
|
return 0; |
132 |
|
else |
133 |
|
return 1; |
134 |
|
} |
135 |
|
|
136 |
const struct floatformat floatformat_i387_ext = |
const struct floatformat floatformat_i387_ext = |
137 |
{ |
{ |
138 |
floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, |
floatformat_little, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, |
139 |
floatformat_intbit_yes, |
floatformat_intbit_yes, |
140 |
"floatformat_i387_ext" |
"floatformat_i387_ext", |
141 |
|
floatformat_i387_ext_is_valid |
142 |
}; |
}; |
143 |
const struct floatformat floatformat_m68881_ext = |
const struct floatformat floatformat_m68881_ext = |
144 |
{ |
{ |
145 |
/* Note that the bits from 16 to 31 are unused. */ |
/* Note that the bits from 16 to 31 are unused. */ |
146 |
floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64, |
floatformat_big, 96, 0, 1, 15, 0x3fff, 0x7fff, 32, 64, |
147 |
floatformat_intbit_yes, |
floatformat_intbit_yes, |
148 |
"floatformat_m68881_ext" |
"floatformat_m68881_ext", |
149 |
|
floatformat_always_valid |
150 |
}; |
}; |
151 |
const struct floatformat floatformat_i960_ext = |
const struct floatformat floatformat_i960_ext = |
152 |
{ |
{ |
153 |
/* Note that the bits from 0 to 15 are unused. */ |
/* Note that the bits from 0 to 15 are unused. */ |
154 |
floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64, |
floatformat_little, 96, 16, 17, 15, 0x3fff, 0x7fff, 32, 64, |
155 |
floatformat_intbit_yes, |
floatformat_intbit_yes, |
156 |
"floatformat_i960_ext" |
"floatformat_i960_ext", |
157 |
|
floatformat_always_valid |
158 |
}; |
}; |
159 |
const struct floatformat floatformat_m88110_ext = |
const struct floatformat floatformat_m88110_ext = |
160 |
{ |
{ |
161 |
#ifdef HARRIS_FLOAT_FORMAT |
floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, |
162 |
|
floatformat_intbit_yes, |
163 |
|
"floatformat_m88110_ext", |
164 |
|
floatformat_always_valid |
165 |
|
}; |
166 |
|
const struct floatformat floatformat_m88110_harris_ext = |
167 |
|
{ |
168 |
/* Harris uses raw format 128 bytes long, but the number is just an ieee |
/* Harris uses raw format 128 bytes long, but the number is just an ieee |
169 |
double, and the last 64 bits are wasted. */ |
double, and the last 64 bits are wasted. */ |
170 |
floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52, |
floatformat_big,128, 0, 1, 11, 0x3ff, 0x7ff, 12, 52, |
171 |
floatformat_intbit_no, |
floatformat_intbit_no, |
172 |
"floatformat_m88110_ext(harris)" |
"floatformat_m88110_ext_harris", |
173 |
#else |
floatformat_always_valid |
|
floatformat_big, 80, 0, 1, 15, 0x3fff, 0x7fff, 16, 64, |
|
|
floatformat_intbit_yes, |
|
|
"floatformat_m88110_ext" |
|
|
#endif /* HARRIS_FLOAT_FORMAT */ |
|
174 |
}; |
}; |
175 |
const struct floatformat floatformat_arm_ext = |
const struct floatformat floatformat_arm_ext_big = |
176 |
{ |
{ |
177 |
/* Bits 1 to 16 are unused. */ |
/* Bits 1 to 16 are unused. */ |
178 |
floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, |
floatformat_big, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, |
179 |
floatformat_intbit_yes, |
floatformat_intbit_yes, |
180 |
"floatformat_arm_ext" |
"floatformat_arm_ext_big", |
181 |
|
floatformat_always_valid |
182 |
|
}; |
183 |
|
const struct floatformat floatformat_arm_ext_littlebyte_bigword = |
184 |
|
{ |
185 |
|
/* Bits 1 to 16 are unused. */ |
186 |
|
floatformat_littlebyte_bigword, 96, 0, 17, 15, 0x3fff, 0x7fff, 32, 64, |
187 |
|
floatformat_intbit_yes, |
188 |
|
"floatformat_arm_ext_littlebyte_bigword", |
189 |
|
floatformat_always_valid |
190 |
|
}; |
191 |
|
const struct floatformat floatformat_ia64_spill_big = |
192 |
|
{ |
193 |
|
floatformat_big, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64, |
194 |
|
floatformat_intbit_yes, |
195 |
|
"floatformat_ia64_spill_big", |
196 |
|
floatformat_always_valid |
197 |
|
}; |
198 |
|
const struct floatformat floatformat_ia64_spill_little = |
199 |
|
{ |
200 |
|
floatformat_little, 128, 0, 1, 17, 65535, 0x1ffff, 18, 64, |
201 |
|
floatformat_intbit_yes, |
202 |
|
"floatformat_ia64_spill_little", |
203 |
|
floatformat_always_valid |
204 |
|
}; |
205 |
|
const struct floatformat floatformat_ia64_quad_big = |
206 |
|
{ |
207 |
|
floatformat_big, 128, 0, 1, 15, 16383, 0x7fff, 16, 112, |
208 |
|
floatformat_intbit_no, |
209 |
|
"floatformat_ia64_quad_big", |
210 |
|
floatformat_always_valid |
211 |
|
}; |
212 |
|
const struct floatformat floatformat_ia64_quad_little = |
213 |
|
{ |
214 |
|
floatformat_little, 128, 0, 1, 15, 16383, 0x7fff, 16, 112, |
215 |
|
floatformat_intbit_no, |
216 |
|
"floatformat_ia64_quad_little", |
217 |
|
floatformat_always_valid |
218 |
}; |
}; |
219 |
|
|
220 |
static unsigned long get_field PARAMS ((unsigned char *, |
/* Extract a field which starts at START and is LEN bits long. DATA and |
|
enum floatformat_byteorders, |
|
|
unsigned int, |
|
|
unsigned int, |
|
|
unsigned int)); |
|
|
|
|
|
/* Extract a field which starts at START and is LEN bytes long. DATA and |
|
221 |
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ |
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ |
222 |
static unsigned long |
static unsigned long |
223 |
get_field (data, order, total_len, start, len) |
get_field (data, order, total_len, start, len) |
224 |
unsigned char *data; |
const unsigned char *data; |
225 |
enum floatformat_byteorders order; |
enum floatformat_byteorders order; |
226 |
unsigned int total_len; |
unsigned int total_len; |
227 |
unsigned int start; |
unsigned int start; |
275 |
void |
void |
276 |
floatformat_to_double (fmt, from, to) |
floatformat_to_double (fmt, from, to) |
277 |
const struct floatformat *fmt; |
const struct floatformat *fmt; |
278 |
char *from; |
const char *from; |
279 |
double *to; |
double *to; |
280 |
{ |
{ |
281 |
unsigned char *ufrom = (unsigned char *)from; |
const unsigned char *ufrom = (const unsigned char *)from; |
282 |
double dto; |
double dto; |
283 |
long exponent; |
long exponent; |
284 |
unsigned long mant; |
unsigned long mant; |
288 |
|
|
289 |
exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, |
exponent = get_field (ufrom, fmt->byteorder, fmt->totalsize, |
290 |
fmt->exp_start, fmt->exp_len); |
fmt->exp_start, fmt->exp_len); |
291 |
/* Note that if exponent indicates a NaN, we can't really do anything useful |
|
292 |
(not knowing if the host has NaN's, or how to build one). So it will |
/* If the exponent indicates a NaN, we don't have information to |
293 |
end up as an infinity or something close; that is OK. */ |
decide what to do. So we handle it like IEEE, except that we |
294 |
|
don't try to preserve the type of NaN. FIXME. */ |
295 |
|
if ((unsigned long) exponent == fmt->exp_nan) |
296 |
|
{ |
297 |
|
int nan; |
298 |
|
|
299 |
|
mant_off = fmt->man_start; |
300 |
|
mant_bits_left = fmt->man_len; |
301 |
|
nan = 0; |
302 |
|
while (mant_bits_left > 0) |
303 |
|
{ |
304 |
|
mant_bits = min (mant_bits_left, 32); |
305 |
|
|
306 |
|
if (get_field (ufrom, fmt->byteorder, fmt->totalsize, |
307 |
|
mant_off, mant_bits) != 0) |
308 |
|
{ |
309 |
|
/* This is a NaN. */ |
310 |
|
nan = 1; |
311 |
|
break; |
312 |
|
} |
313 |
|
|
314 |
|
mant_off += mant_bits; |
315 |
|
mant_bits_left -= mant_bits; |
316 |
|
} |
317 |
|
|
318 |
|
if (nan) |
319 |
|
dto = NAN; |
320 |
|
else |
321 |
|
dto = INFINITY; |
322 |
|
|
323 |
|
if (get_field (ufrom, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1)) |
324 |
|
dto = -dto; |
325 |
|
|
326 |
|
*to = dto; |
327 |
|
|
328 |
|
return; |
329 |
|
} |
330 |
|
|
331 |
mant_bits_left = fmt->man_len; |
mant_bits_left = fmt->man_len; |
332 |
mant_off = fmt->man_start; |
mant_off = fmt->man_start; |
359 |
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, |
mant = get_field (ufrom, fmt->byteorder, fmt->totalsize, |
360 |
mant_off, mant_bits); |
mant_off, mant_bits); |
361 |
|
|
362 |
dto += ldexp ((double)mant, exponent - mant_bits); |
/* Handle denormalized numbers. FIXME: What should we do for |
363 |
exponent -= mant_bits; |
non-IEEE formats? */ |
364 |
|
if (exponent == 0 && mant != 0) |
365 |
|
dto += ldexp ((double)mant, |
366 |
|
(- fmt->exp_bias |
367 |
|
- mant_bits |
368 |
|
- (mant_off - fmt->man_start) |
369 |
|
+ 1)); |
370 |
|
else |
371 |
|
dto += ldexp ((double)mant, exponent - mant_bits); |
372 |
|
if (exponent != 0) |
373 |
|
exponent -= mant_bits; |
374 |
mant_off += mant_bits; |
mant_off += mant_bits; |
375 |
mant_bits_left -= mant_bits; |
mant_bits_left -= mant_bits; |
376 |
} |
} |
387 |
unsigned int, |
unsigned int, |
388 |
unsigned long)); |
unsigned long)); |
389 |
|
|
390 |
/* Set a field which starts at START and is LEN bytes long. DATA and |
/* Set a field which starts at START and is LEN bits long. DATA and |
391 |
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ |
TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ |
392 |
static void |
static void |
393 |
put_field (data, order, total_len, start, len, stuff_to_put) |
put_field (data, order, total_len, start, len, stuff_to_put) |
445 |
void |
void |
446 |
floatformat_from_double (fmt, from, to) |
floatformat_from_double (fmt, from, to) |
447 |
const struct floatformat *fmt; |
const struct floatformat *fmt; |
448 |
double *from; |
const double *from; |
449 |
char *to; |
char *to; |
450 |
{ |
{ |
451 |
double dfrom; |
double dfrom; |
455 |
int mant_bits_left; |
int mant_bits_left; |
456 |
unsigned char *uto = (unsigned char *)to; |
unsigned char *uto = (unsigned char *)to; |
457 |
|
|
458 |
memcpy (&dfrom, from, sizeof (dfrom)); |
dfrom = *from; |
459 |
memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT); |
memset (uto, 0, fmt->totalsize / FLOATFORMAT_CHAR_BIT); |
460 |
|
|
461 |
|
/* If negative, set the sign bit. */ |
462 |
|
if (dfrom < 0) |
463 |
|
{ |
464 |
|
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); |
465 |
|
dfrom = -dfrom; |
466 |
|
} |
467 |
|
|
468 |
if (dfrom == 0) |
if (dfrom == 0) |
469 |
return; /* Result is zero */ |
{ |
470 |
|
/* 0.0. */ |
471 |
|
return; |
472 |
|
} |
473 |
|
|
474 |
if (dfrom != dfrom) |
if (dfrom != dfrom) |
475 |
{ |
{ |
476 |
/* From is NaN */ |
/* NaN. */ |
477 |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, |
478 |
fmt->exp_len, fmt->exp_nan); |
fmt->exp_len, fmt->exp_nan); |
479 |
/* Be sure it's not infinity, but NaN value is irrel */ |
/* Be sure it's not infinity, but NaN value is irrelevant. */ |
480 |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->man_start, |
481 |
32, 1); |
32, 1); |
482 |
return; |
return; |
483 |
} |
} |
484 |
|
|
485 |
/* If negative, set the sign bit. */ |
if (dfrom + dfrom == dfrom) |
|
if (dfrom < 0) |
|
486 |
{ |
{ |
487 |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->sign_start, 1, 1); |
/* This can only happen for an infinite value (or zero, which we |
488 |
dfrom = -dfrom; |
already handled above). */ |
489 |
|
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, |
490 |
|
fmt->exp_len, fmt->exp_nan); |
491 |
|
return; |
492 |
} |
} |
493 |
|
|
|
/* How to tell an infinity from an ordinary number? FIXME-someday */ |
|
|
|
|
494 |
mant = frexp (dfrom, &exponent); |
mant = frexp (dfrom, &exponent); |
495 |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, fmt->exp_len, |
if (exponent + fmt->exp_bias - 1 > 0) |
496 |
exponent + fmt->exp_bias - 1); |
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, |
497 |
|
fmt->exp_len, exponent + fmt->exp_bias - 1); |
498 |
|
else |
499 |
|
{ |
500 |
|
/* Handle a denormalized number. FIXME: What should we do for |
501 |
|
non-IEEE formats? */ |
502 |
|
put_field (uto, fmt->byteorder, fmt->totalsize, fmt->exp_start, |
503 |
|
fmt->exp_len, 0); |
504 |
|
mant = ldexp (mant, exponent + fmt->exp_bias - 1); |
505 |
|
} |
506 |
|
|
507 |
mant_bits_left = fmt->man_len; |
mant_bits_left = fmt->man_len; |
508 |
mant_off = fmt->man_start; |
mant_off = fmt->man_start; |
515 |
mant_long = (unsigned long)mant; |
mant_long = (unsigned long)mant; |
516 |
mant -= mant_long; |
mant -= mant_long; |
517 |
|
|
518 |
/* If the integer bit is implicit, then we need to discard it. |
/* If the integer bit is implicit, and we are not creating a |
519 |
If we are discarding a zero, we should be (but are not) creating |
denormalized number, then we need to discard it. */ |
|
a denormalized number which means adjusting the exponent |
|
|
(I think). */ |
|
520 |
if ((unsigned int) mant_bits_left == fmt->man_len |
if ((unsigned int) mant_bits_left == fmt->man_len |
521 |
&& fmt->intbit == floatformat_intbit_no) |
&& fmt->intbit == floatformat_intbit_no |
522 |
|
&& exponent + fmt->exp_bias - 1 > 0) |
523 |
{ |
{ |
524 |
mant_long &= 0x7fffffff; |
mant_long &= 0x7fffffff; |
525 |
mant_bits -= 1; |
mant_bits -= 1; |
538 |
} |
} |
539 |
} |
} |
540 |
|
|
541 |
|
/* Return non-zero iff the data at FROM is a valid number in format FMT. */ |
542 |
|
|
543 |
|
int |
544 |
|
floatformat_is_valid (fmt, from) |
545 |
|
const struct floatformat *fmt; |
546 |
|
const char *from; |
547 |
|
{ |
548 |
|
return fmt->is_valid (fmt, from); |
549 |
|
} |
550 |
|
|
551 |
|
|
552 |
#ifdef IEEE_DEBUG |
#ifdef IEEE_DEBUG |
553 |
|
|
554 |
|
#include <stdio.h> |
555 |
|
|
556 |
/* This is to be run on a host which uses IEEE floating point. */ |
/* This is to be run on a host which uses IEEE floating point. */ |
557 |
|
|
558 |
void |
void |
560 |
double n; |
double n; |
561 |
{ |
{ |
562 |
double result; |
double result; |
|
char exten[16]; |
|
563 |
|
|
564 |
floatformat_to_double (&floatformat_ieee_double_big, &n, &result); |
floatformat_to_double (&floatformat_ieee_double_little, (char *) &n, |
565 |
if (n != result) |
&result); |
566 |
|
if ((n != result && (! isnan (n) || ! isnan (result))) |
567 |
|
|| (n < 0 && result >= 0) |
568 |
|
|| (n >= 0 && result < 0)) |
569 |
printf ("Differ(to): %.20g -> %.20g\n", n, result); |
printf ("Differ(to): %.20g -> %.20g\n", n, result); |
570 |
floatformat_from_double (&floatformat_ieee_double_big, &n, &result); |
|
571 |
if (n != result) |
floatformat_from_double (&floatformat_ieee_double_little, &n, |
572 |
|
(char *) &result); |
573 |
|
if ((n != result && (! isnan (n) || ! isnan (result))) |
574 |
|
|| (n < 0 && result >= 0) |
575 |
|
|| (n >= 0 && result < 0)) |
576 |
printf ("Differ(from): %.20g -> %.20g\n", n, result); |
printf ("Differ(from): %.20g -> %.20g\n", n, result); |
577 |
|
|
578 |
floatformat_from_double (&floatformat_m68881_ext, &n, exten); |
#if 0 |
579 |
floatformat_to_double (&floatformat_m68881_ext, exten, &result); |
{ |
580 |
if (n != result) |
char exten[16]; |
581 |
printf ("Differ(to+from): %.20g -> %.20g\n", n, result); |
|
582 |
|
floatformat_from_double (&floatformat_m68881_ext, &n, exten); |
583 |
|
floatformat_to_double (&floatformat_m68881_ext, exten, &result); |
584 |
|
if (n != result) |
585 |
|
printf ("Differ(to+from): %.20g -> %.20g\n", n, result); |
586 |
|
} |
587 |
|
#endif |
588 |
|
|
589 |
#if IEEE_DEBUG > 1 |
#if IEEE_DEBUG > 1 |
590 |
/* This is to be run on a host which uses 68881 format. */ |
/* This is to be run on a host which uses 68881 format. */ |
599 |
int |
int |
600 |
main () |
main () |
601 |
{ |
{ |
602 |
|
ieee_test (0.0); |
603 |
ieee_test (0.5); |
ieee_test (0.5); |
604 |
ieee_test (256.0); |
ieee_test (256.0); |
605 |
ieee_test (0.12345); |
ieee_test (0.12345); |
606 |
ieee_test (234235.78907234); |
ieee_test (234235.78907234); |
607 |
ieee_test (-512.0); |
ieee_test (-512.0); |
608 |
ieee_test (-0.004321); |
ieee_test (-0.004321); |
609 |
|
ieee_test (1.2E-70); |
610 |
|
ieee_test (1.2E-316); |
611 |
|
ieee_test (4.9406564584124654E-324); |
612 |
|
ieee_test (- 4.9406564584124654E-324); |
613 |
|
ieee_test (- 0.0); |
614 |
|
ieee_test (- INFINITY); |
615 |
|
ieee_test (- NAN); |
616 |
|
ieee_test (INFINITY); |
617 |
|
ieee_test (NAN); |
618 |
return 0; |
return 0; |
619 |
} |
} |
620 |
#endif |
#endif |