Daily bump.
[official-gcc.git] / gcc / config / dfp-bit.c
blobac574434dfbfab13670a38b5ac2370c35ee3f6f4
1 /* This is a software decimal floating point library.
2 Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
11 In addition to the permissions in the GNU General Public License, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of this file into combinations with other programs,
14 and to distribute those combinations without any restriction coming
15 from the use of this file. (The General Public License restrictions
16 do apply in other respects; for example, they cover modification of
17 the file, and distribution when not linked into a combine
18 executable.)
20 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
21 WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
25 You should have received a copy of the GNU General Public License
26 along with GCC; see the file COPYING. If not, write to the Free
27 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
28 02110-1301, USA. */
30 /* This implements IEEE 754R decimal floating point arithmetic, but
31 does not provide a mechanism for setting the rounding mode, or for
32 generating or handling exceptions. Conversions between decimal
33 floating point types and other types depend on C library functions.
35 Contributed by Ben Elliston <bje@au.ibm.com>. */
37 #include <stdio.h>
38 #include <stdlib.h>
39 /* FIXME: compile with -std=gnu99 to get these from stdlib.h */
40 extern float strtof (const char *, char **);
41 extern long double strtold (const char *, char **);
42 #include <string.h>
43 #include <limits.h>
45 #include "config/dfp-bit.h"
47 /* Forward declarations. */
48 #if WIDTH == 32 || WIDTH_TO == 32
49 void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
50 void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
51 #endif
52 #if WIDTH == 64 || WIDTH_TO == 64
53 void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
54 void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
55 #endif
56 #if WIDTH == 128 || WIDTH_TO == 128
57 void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
58 void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
59 #endif
61 /* A pointer to a binary decFloat operation. */
62 typedef decFloat* (*dfp_binary_func)
63 (decFloat *, const decFloat *, const decFloat *, decContext *);
65 /* Binary operations. */
67 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
68 binary operation. */
69 static inline decFloat
70 dfp_binary_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
72 decFloat result;
73 decContext context;
75 decContextDefault (&context, CONTEXT_INIT);
76 DFP_INIT_ROUNDMODE (context.round);
78 /* Perform the operation. */
79 op (&result, &arg_a, &arg_b, &context);
81 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
83 /* decNumber exception flags we care about here. */
84 int ieee_flags;
85 int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
86 | DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
87 | DEC_IEEE_854_Underflow;
88 dec_flags &= context.status;
89 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
90 if (ieee_flags != 0)
91 DFP_HANDLE_EXCEPTIONS (ieee_flags);
94 return result;
97 #if WIDTH == 32
98 /* The decNumber package doesn't provide arithmetic for decSingle (32 bits);
99 convert to decDouble, use the operation for that, and convert back. */
100 static inline _Decimal32
101 d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
103 union { _Decimal32 c; decSingle f; } a32, b32, res32;
104 decDouble a, b, res;
105 decContext context;
107 /* Widen the operands and perform the operation. */
108 a32.c = arg_a;
109 b32.c = arg_b;
110 decSingleToWider (&a32.f, &a);
111 decSingleToWider (&b32.f, &b);
112 res = dfp_binary_op (op, a, b);
114 /* Narrow the result, which might result in an underflow or overflow. */
115 decContextDefault (&context, CONTEXT_INIT);
116 DFP_INIT_ROUNDMODE (context.round);
117 decSingleFromWider (&res32.f, &res, &context);
118 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
120 /* decNumber exception flags we care about here. */
121 int ieee_flags;
122 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow
123 | DEC_IEEE_854_Underflow;
124 dec_flags &= context.status;
125 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
126 if (ieee_flags != 0)
127 DFP_HANDLE_EXCEPTIONS (ieee_flags);
130 return res32.c;
132 #else
133 /* decFloat operations are supported for decDouble (64 bits) and
134 decQuad (128 bits). The bit patterns for the types are the same. */
135 static inline DFP_C_TYPE
136 dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
138 union { DFP_C_TYPE c; decFloat f; } a, b, result;
140 a.c = arg_a;
141 b.c = arg_b;
142 result.f = dfp_binary_op (op, a.f, b.f);
143 return result.c;
145 #endif
147 /* Comparison operations. */
149 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
150 comparison. */
151 static inline CMPtype
152 dfp_compare_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
154 decContext context;
155 decFloat res;
156 int result;
158 decContextDefault (&context, CONTEXT_INIT);
159 DFP_INIT_ROUNDMODE (context.round);
161 /* Perform the comparison. */
162 op (&res, &arg_a, &arg_b, &context);
164 if (DEC_FLOAT_IS_SIGNED (&res))
165 result = -1;
166 else if (DEC_FLOAT_IS_ZERO (&res))
167 result = 0;
168 else if (DEC_FLOAT_IS_NAN (&res))
169 result = -2;
170 else
171 result = 1;
173 return (CMPtype) result;
176 #if WIDTH == 32
177 /* The decNumber package doesn't provide comparisons for decSingle (32 bits);
178 convert to decDouble, use the operation for that, and convert back. */
179 static inline CMPtype
180 d32_compare_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
182 union { _Decimal32 c; decSingle f; } a32, b32;
183 decDouble a, b;
185 a32.c = arg_a;
186 b32.c = arg_b;
187 decSingleToWider (&a32.f, &a);
188 decSingleToWider (&b32.f, &b);
189 return dfp_compare_op (op, a, b);
191 #else
192 /* decFloat comparisons are supported for decDouble (64 bits) and
193 decQuad (128 bits). The bit patterns for the types are the same. */
194 static inline CMPtype
195 dnn_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
197 union { DFP_C_TYPE c; decFloat f; } a, b;
199 a.c = arg_a;
200 b.c = arg_b;
201 return dfp_compare_op (op, a.f, b.f);
203 #endif
205 #if defined(L_conv_sd)
206 void
207 __host_to_ieee_32 (_Decimal32 in, decimal32 *out)
209 memcpy (out, &in, 4);
212 void
213 __ieee_to_host_32 (decimal32 in, _Decimal32 *out)
215 memcpy (out, &in, 4);
217 #endif /* L_conv_sd */
219 #if defined(L_conv_dd)
220 void
221 __host_to_ieee_64 (_Decimal64 in, decimal64 *out)
223 memcpy (out, &in, 8);
226 void
227 __ieee_to_host_64 (decimal64 in, _Decimal64 *out)
229 memcpy (out, &in, 8);
231 #endif /* L_conv_dd */
233 #if defined(L_conv_td)
234 void
235 __host_to_ieee_128 (_Decimal128 in, decimal128 *out)
237 memcpy (out, &in, 16);
240 void
241 __ieee_to_host_128 (decimal128 in, _Decimal128 *out)
243 memcpy (out, &in, 16);
245 #endif /* L_conv_td */
247 #if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
248 DFP_C_TYPE
249 DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
251 return DFP_BINARY_OP (DEC_FLOAT_ADD, arg_a, arg_b);
254 DFP_C_TYPE
255 DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
257 return DFP_BINARY_OP (DEC_FLOAT_SUBTRACT, arg_a, arg_b);
259 #endif /* L_addsub */
261 #if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
262 DFP_C_TYPE
263 DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
265 return DFP_BINARY_OP (DEC_FLOAT_MULTIPLY, arg_a, arg_b);
267 #endif /* L_mul */
269 #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
270 DFP_C_TYPE
271 DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
273 return DFP_BINARY_OP (DEC_FLOAT_DIVIDE, arg_a, arg_b);
275 #endif /* L_div */
277 #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
278 CMPtype
279 DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
281 CMPtype stat;
282 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
283 /* For EQ return zero for true, nonzero for false. */
284 return stat != 0;
286 #endif /* L_eq */
288 #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
289 CMPtype
290 DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
292 int stat;
293 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
294 /* For NE return zero for true, nonzero for false. */
295 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
296 return 1;
297 return stat != 0;
299 #endif /* L_ne */
301 #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
302 CMPtype
303 DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
305 int stat;
306 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
307 /* For LT return -1 (<0) for true, 1 for false. */
308 return (stat == -1) ? -1 : 1;
310 #endif /* L_lt */
312 #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
313 CMPtype
314 DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
316 int stat;
317 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
318 /* For GT return 1 (>0) for true, -1 for false. */
319 return (stat == 1) ? 1 : -1;
321 #endif
323 #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
324 CMPtype
325 DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
327 int stat;
328 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
329 /* For LE return 0 (<= 0) for true, 1 for false. */
330 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
331 return 1;
332 return stat == 1;
334 #endif /* L_le */
336 #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
337 CMPtype
338 DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
340 int stat;
341 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
342 /* For GE return 1 (>=0) for true, -1 for false. */
343 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
344 return -1;
345 return (stat != -1) ? 1 : -1;
347 #endif /* L_ge */
349 #define BUFMAX 128
351 /* Check for floating point exceptions that are relevant for conversions
352 between decimal float values and handle them. */
353 static inline void
354 dfp_conversion_exceptions (const int status)
356 /* decNumber exception flags we care about here. */
357 int ieee_flags;
358 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
359 | DEC_IEEE_854_Overflow;
360 dec_flags &= status;
361 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
362 if (ieee_flags != 0)
363 DFP_HANDLE_EXCEPTIONS (ieee_flags);
366 #if defined (L_sd_to_dd)
367 /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
368 _Decimal64
369 DFP_TO_DFP (_Decimal32 f_from)
371 union { _Decimal32 c; decSingle f; } from;
372 union { _Decimal64 c; decDouble f; } to;
374 from.c = f_from;
375 to.f = *decSingleToWider (&from.f, &to.f);
376 return to.c;
378 #endif
380 #if defined (L_sd_to_td)
381 /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
382 _Decimal128
383 DFP_TO_DFP (_Decimal32 f_from)
385 union { _Decimal32 c; decSingle f; } from;
386 union { _Decimal128 c; decQuad f; } to;
387 decDouble temp;
389 from.c = f_from;
390 temp = *decSingleToWider (&from.f, &temp);
391 to.f = *decDoubleToWider (&temp, &to.f);
392 return to.c;
394 #endif
396 #if defined (L_dd_to_td)
397 /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
398 _Decimal128
399 DFP_TO_DFP (_Decimal64 f_from)
401 union { _Decimal64 c; decDouble f; } from;
402 union { _Decimal128 c; decQuad f; } to;
404 from.c = f_from;
405 to.f = *decDoubleToWider (&from.f, &to.f);
406 return to.c;
408 #endif
410 #if defined (L_dd_to_sd)
411 /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
412 _Decimal32
413 DFP_TO_DFP (_Decimal64 f_from)
415 union { _Decimal32 c; decSingle f; } to;
416 union { _Decimal64 c; decDouble f; } from;
417 decContext context;
419 decContextDefault (&context, CONTEXT_INIT);
420 DFP_INIT_ROUNDMODE (context.round);
421 from.c = f_from;
422 to.f = *decSingleFromWider (&to.f, &from.f, &context);
423 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
424 dfp_conversion_exceptions (context.status);
425 return to.c;
427 #endif
429 #if defined (L_td_to_sd)
430 /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
431 _Decimal32
432 DFP_TO_DFP (_Decimal128 f_from)
434 union { _Decimal32 c; decSingle f; } to;
435 union { _Decimal128 c; decQuad f; } from;
436 decDouble temp;
437 decContext context;
439 decContextDefault (&context, CONTEXT_INIT);
440 DFP_INIT_ROUNDMODE (context.round);
441 from.c = f_from;
442 temp = *decDoubleFromWider (&temp, &from.f, &context);
443 to.f = *decSingleFromWider (&to.f, &temp, &context);
444 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
445 dfp_conversion_exceptions (context.status);
446 return to.c;
448 #endif
450 #if defined (L_td_to_dd)
451 /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
452 _Decimal64
453 DFP_TO_DFP (_Decimal128 f_from)
455 union { _Decimal64 c; decDouble f; } to;
456 union { _Decimal128 c; decQuad f; } from;
457 decContext context;
459 decContextDefault (&context, CONTEXT_INIT);
460 DFP_INIT_ROUNDMODE (context.round);
461 from.c = f_from;
462 to.f = *decDoubleFromWider (&to.f, &from.f, &context);
463 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
464 dfp_conversion_exceptions (context.status);
465 return to.c;
467 #endif
469 #if defined (L_dd_to_si) || defined (L_td_to_si) \
470 || defined (L_dd_to_usi) || defined (L_td_to_usi)
471 /* Use decNumber to convert directly from decimal float to integer types. */
472 INT_TYPE
473 DFP_TO_INT (DFP_C_TYPE x)
475 union { DFP_C_TYPE c; decFloat f; } u;
476 decContext context;
477 INT_TYPE i;
479 decContextDefault (&context, DEC_INIT_DECIMAL128);
480 context.round = DEC_ROUND_DOWN;
481 u.c = x;
482 i = DEC_FLOAT_TO_INT (&u.f, &context, context.round);
483 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
484 dfp_conversion_exceptions (context.status);
485 return i;
487 #endif
489 #if defined (L_sd_to_si) || (L_sd_to_usi)
490 /* Use decNumber to convert directly from decimal float to integer types. */
491 INT_TYPE
492 DFP_TO_INT (_Decimal32 x)
494 union { _Decimal32 c; decSingle f; } u32;
495 decDouble f64;
496 decContext context;
497 INT_TYPE i;
499 decContextDefault (&context, DEC_INIT_DECIMAL128);
500 context.round = DEC_ROUND_DOWN;
501 u32.c = x;
502 f64 = *decSingleToWider (&u32.f, &f64);
503 i = DEC_FLOAT_TO_INT (&f64, &context, context.round);
504 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
505 dfp_conversion_exceptions (context.status);
506 return i;
508 #endif
510 #if defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
511 || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
512 /* decNumber doesn't provide support for conversions to 64-bit integer
513 types, so do it the hard way. */
514 INT_TYPE
515 DFP_TO_INT (DFP_C_TYPE x)
517 /* decNumber's decimal* types have the same format as C's _Decimal*
518 types, but they have different calling conventions. */
520 /* TODO: Decimal float to integer conversions should raise FE_INVALID
521 if the result value does not fit into the result type. */
523 IEEE_TYPE s;
524 char buf[BUFMAX];
525 char *pos;
526 decNumber qval, n1, n2;
527 decContext context;
529 /* Use a large context to avoid losing precision. */
530 decContextDefault (&context, DEC_INIT_DECIMAL128);
531 /* Need non-default rounding mode here. */
532 context.round = DEC_ROUND_DOWN;
534 HOST_TO_IEEE (x, &s);
535 TO_INTERNAL (&s, &n1);
536 /* Rescale if the exponent is less than zero. */
537 decNumberToIntegralValue (&n2, &n1, &context);
538 /* Get a value to use for the quantize call. */
539 decNumberFromString (&qval, (char *) "1.", &context);
540 /* Force the exponent to zero. */
541 decNumberQuantize (&n1, &n2, &qval, &context);
542 /* Get a string, which at this point will not include an exponent. */
543 decNumberToString (&n1, buf);
544 /* Ignore the fractional part. */
545 pos = strchr (buf, '.');
546 if (pos)
547 *pos = 0;
548 /* Use a C library function to convert to the integral type. */
549 return STR_TO_INT (buf, NULL, 10);
551 #endif
553 #if defined (L_si_to_dd) || defined (L_si_to_td) \
554 || defined (L_usi_to_dd) || defined (L_usi_to_td)
555 /* Use decNumber to convert directly from integer to decimal float types. */
556 DFP_C_TYPE
557 INT_TO_DFP (INT_TYPE i)
559 union { DFP_C_TYPE c; decFloat f; } u;
561 u.f = *DEC_FLOAT_FROM_INT (&u.f, i);
562 return u.c;
564 #endif
566 #if defined (L_si_to_sd) || defined (L_usi_to_sd)
567 _Decimal32
568 /* Use decNumber to convert directly from integer to decimal float types. */
569 INT_TO_DFP (INT_TYPE i)
571 union { _Decimal32 c; decSingle f; } u32;
572 decDouble f64;
573 decContext context;
575 decContextDefault (&context, DEC_INIT_DECIMAL128);
576 context.round = DEC_ROUND_DOWN;
577 f64 = *DEC_FLOAT_FROM_INT (&f64, i);
578 u32.f = *decSingleFromWider (&u32.f, &f64, &context);
579 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
580 dfp_conversion_exceptions (context.status);
581 return u32.c;
583 #endif
585 #if defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
586 || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
587 /* decNumber doesn't provide support for conversions from 64-bit integer
588 types, so do it the hard way. */
589 DFP_C_TYPE
590 INT_TO_DFP (INT_TYPE i)
592 DFP_C_TYPE f;
593 IEEE_TYPE s;
594 char buf[BUFMAX];
595 decContext context;
597 decContextDefault (&context, CONTEXT_INIT);
598 DFP_INIT_ROUNDMODE (context.round);
600 /* Use a C library function to get a floating point string. */
601 sprintf (buf, INT_FMT ".0", CAST_FOR_FMT(i));
602 /* Convert from the floating point string to a decimal* type. */
603 FROM_STRING (&s, buf, &context);
604 IEEE_TO_HOST (s, &f);
606 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
607 dfp_conversion_exceptions (context.status);
609 return f;
611 #endif
613 #if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
614 || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
615 || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
616 && LONG_DOUBLE_HAS_XF_MODE) \
617 || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
618 && LONG_DOUBLE_HAS_TF_MODE)
619 BFP_TYPE
620 DFP_TO_BFP (DFP_C_TYPE f)
622 IEEE_TYPE s;
623 char buf[BUFMAX];
625 HOST_TO_IEEE (f, &s);
626 /* Write the value to a string. */
627 TO_STRING (&s, buf);
628 /* Read it as the binary floating point type and return that. */
629 return STR_TO_BFP (buf, NULL);
631 #endif
633 #if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
634 || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
635 || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
636 && LONG_DOUBLE_HAS_XF_MODE) \
637 || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
638 && LONG_DOUBLE_HAS_TF_MODE)
639 DFP_C_TYPE
640 BFP_TO_DFP (BFP_TYPE x)
642 DFP_C_TYPE f;
643 IEEE_TYPE s;
644 char buf[BUFMAX];
645 decContext context;
647 decContextDefault (&context, CONTEXT_INIT);
648 DFP_INIT_ROUNDMODE (context.round);
650 /* Use a C library function to write the floating point value to a string. */
651 sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
653 /* Convert from the floating point string to a decimal* type. */
654 FROM_STRING (&s, buf, &context);
655 IEEE_TO_HOST (s, &f);
657 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
659 /* decNumber exception flags we care about here. */
660 int ieee_flags;
661 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
662 | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
663 dec_flags &= context.status;
664 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
665 if (ieee_flags != 0)
666 DFP_HANDLE_EXCEPTIONS (ieee_flags);
669 return f;
671 #endif
673 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
674 CMPtype
675 DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
677 decNumber arg1, arg2;
678 IEEE_TYPE a, b;
680 HOST_TO_IEEE (arg_a, &a);
681 HOST_TO_IEEE (arg_b, &b);
682 TO_INTERNAL (&a, &arg1);
683 TO_INTERNAL (&b, &arg2);
684 return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
686 #endif /* L_unord_sd || L_unord_dd || L_unord_td */