Fix typo in my last change
[official-gcc.git] / libgcc / dfp-bit.c
blob48dcb735510a9de13dbfd9b3e947f641631d14c2
1 /* This is a software decimal floating point library.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011
3 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 /* This implements IEEE 754 decimal floating point arithmetic, but
27 does not provide a mechanism for setting the rounding mode, or for
28 generating or handling exceptions. Conversions between decimal
29 floating point types and other types depend on C library functions.
31 Contributed by Ben Elliston <bje@au.ibm.com>. */
33 #include <stdio.h>
34 #include <stdlib.h>
35 /* FIXME: compile with -std=gnu99 to get these from stdlib.h */
36 extern float strtof (const char *, char **);
37 extern long double strtold (const char *, char **);
38 #include <string.h>
39 #include <limits.h>
41 #include "dfp-bit.h"
43 /* Forward declarations. */
44 #if WIDTH == 32 || WIDTH_TO == 32
45 void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
46 void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
47 #endif
48 #if WIDTH == 64 || WIDTH_TO == 64
49 void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
50 void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
51 #endif
52 #if WIDTH == 128 || WIDTH_TO == 128
53 void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
54 void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
55 #endif
57 /* A pointer to a binary decFloat operation. */
58 typedef decFloat* (*dfp_binary_func)
59 (decFloat *, const decFloat *, const decFloat *, decContext *);
61 /* Binary operations. */
63 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
64 binary operation. */
65 static inline decFloat
66 dfp_binary_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
68 decFloat result;
69 decContext context;
71 decContextDefault (&context, CONTEXT_INIT);
72 DFP_INIT_ROUNDMODE (context.round);
74 /* Perform the operation. */
75 op (&result, &arg_a, &arg_b, &context);
77 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
79 /* decNumber exception flags we care about here. */
80 int ieee_flags;
81 int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
82 | DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
83 | DEC_IEEE_854_Underflow;
84 dec_flags &= context.status;
85 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
86 if (ieee_flags != 0)
87 DFP_HANDLE_EXCEPTIONS (ieee_flags);
90 return result;
93 #if WIDTH == 32
94 /* The decNumber package doesn't provide arithmetic for decSingle (32 bits);
95 convert to decDouble, use the operation for that, and convert back. */
96 static inline _Decimal32
97 d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
99 union { _Decimal32 c; decSingle f; } a32, b32, res32;
100 decDouble a, b, res;
101 decContext context;
103 /* Widen the operands and perform the operation. */
104 a32.c = arg_a;
105 b32.c = arg_b;
106 decSingleToWider (&a32.f, &a);
107 decSingleToWider (&b32.f, &b);
108 res = dfp_binary_op (op, a, b);
110 /* Narrow the result, which might result in an underflow or overflow. */
111 decContextDefault (&context, CONTEXT_INIT);
112 DFP_INIT_ROUNDMODE (context.round);
113 decSingleFromWider (&res32.f, &res, &context);
114 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
116 /* decNumber exception flags we care about here. */
117 int ieee_flags;
118 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow
119 | DEC_IEEE_854_Underflow;
120 dec_flags &= context.status;
121 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
122 if (ieee_flags != 0)
123 DFP_HANDLE_EXCEPTIONS (ieee_flags);
126 return res32.c;
128 #else
129 /* decFloat operations are supported for decDouble (64 bits) and
130 decQuad (128 bits). The bit patterns for the types are the same. */
131 static inline DFP_C_TYPE
132 dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
134 union { DFP_C_TYPE c; decFloat f; } a, b, result;
136 a.c = arg_a;
137 b.c = arg_b;
138 result.f = dfp_binary_op (op, a.f, b.f);
139 return result.c;
141 #endif
143 /* Comparison operations. */
145 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
146 comparison. */
147 static inline CMPtype
148 dfp_compare_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
150 decContext context;
151 decFloat res;
152 int result;
154 decContextDefault (&context, CONTEXT_INIT);
155 DFP_INIT_ROUNDMODE (context.round);
157 /* Perform the comparison. */
158 op (&res, &arg_a, &arg_b, &context);
160 if (DEC_FLOAT_IS_SIGNED (&res))
161 result = -1;
162 else if (DEC_FLOAT_IS_ZERO (&res))
163 result = 0;
164 else if (DEC_FLOAT_IS_NAN (&res))
165 result = -2;
166 else
167 result = 1;
169 return (CMPtype) result;
172 #if WIDTH == 32
173 /* The decNumber package doesn't provide comparisons for decSingle (32 bits);
174 convert to decDouble, use the operation for that, and convert back. */
175 static inline CMPtype
176 d32_compare_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
178 union { _Decimal32 c; decSingle f; } a32, b32;
179 decDouble a, b;
181 a32.c = arg_a;
182 b32.c = arg_b;
183 decSingleToWider (&a32.f, &a);
184 decSingleToWider (&b32.f, &b);
185 return dfp_compare_op (op, a, b);
187 #else
188 /* decFloat comparisons are supported for decDouble (64 bits) and
189 decQuad (128 bits). The bit patterns for the types are the same. */
190 static inline CMPtype
191 dnn_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
193 union { DFP_C_TYPE c; decFloat f; } a, b;
195 a.c = arg_a;
196 b.c = arg_b;
197 return dfp_compare_op (op, a.f, b.f);
199 #endif
201 #if defined(L_conv_sd)
202 void
203 __host_to_ieee_32 (_Decimal32 in, decimal32 *out)
205 memcpy (out, &in, 4);
208 void
209 __ieee_to_host_32 (decimal32 in, _Decimal32 *out)
211 memcpy (out, &in, 4);
213 #endif /* L_conv_sd */
215 #if defined(L_conv_dd)
216 void
217 __host_to_ieee_64 (_Decimal64 in, decimal64 *out)
219 memcpy (out, &in, 8);
222 void
223 __ieee_to_host_64 (decimal64 in, _Decimal64 *out)
225 memcpy (out, &in, 8);
227 #endif /* L_conv_dd */
229 #if defined(L_conv_td)
230 void
231 __host_to_ieee_128 (_Decimal128 in, decimal128 *out)
233 memcpy (out, &in, 16);
236 void
237 __ieee_to_host_128 (decimal128 in, _Decimal128 *out)
239 memcpy (out, &in, 16);
241 #endif /* L_conv_td */
243 #if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
244 DFP_C_TYPE
245 DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
247 return DFP_BINARY_OP (DEC_FLOAT_ADD, arg_a, arg_b);
250 DFP_C_TYPE
251 DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
253 return DFP_BINARY_OP (DEC_FLOAT_SUBTRACT, arg_a, arg_b);
255 #endif /* L_addsub */
257 #if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
258 DFP_C_TYPE
259 DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
261 return DFP_BINARY_OP (DEC_FLOAT_MULTIPLY, arg_a, arg_b);
263 #endif /* L_mul */
265 #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
266 DFP_C_TYPE
267 DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
269 return DFP_BINARY_OP (DEC_FLOAT_DIVIDE, arg_a, arg_b);
271 #endif /* L_div */
273 #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
274 CMPtype
275 DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
277 CMPtype stat;
278 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
279 /* For EQ return zero for true, nonzero for false. */
280 return stat != 0;
282 #endif /* L_eq */
284 #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
285 CMPtype
286 DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
288 int stat;
289 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
290 /* For NE return zero for true, nonzero for false. */
291 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
292 return 1;
293 return stat != 0;
295 #endif /* L_ne */
297 #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
298 CMPtype
299 DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
301 int stat;
302 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
303 /* For LT return -1 (<0) for true, 1 for false. */
304 return (stat == -1) ? -1 : 1;
306 #endif /* L_lt */
308 #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
309 CMPtype
310 DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
312 int stat;
313 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
314 /* For GT return 1 (>0) for true, -1 for false. */
315 return (stat == 1) ? 1 : -1;
317 #endif
319 #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
320 CMPtype
321 DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
323 int stat;
324 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
325 /* For LE return 0 (<= 0) for true, 1 for false. */
326 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
327 return 1;
328 return stat == 1;
330 #endif /* L_le */
332 #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
333 CMPtype
334 DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
336 int stat;
337 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
338 /* For GE return 1 (>=0) for true, -1 for false. */
339 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
340 return -1;
341 return (stat != -1) ? 1 : -1;
343 #endif /* L_ge */
345 #define BUFMAX 128
347 /* Check for floating point exceptions that are relevant for conversions
348 between decimal float values and handle them. */
349 static inline void
350 dfp_conversion_exceptions (const int status)
352 /* decNumber exception flags we care about here. */
353 int ieee_flags;
354 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
355 | DEC_IEEE_854_Overflow;
356 dec_flags &= status;
357 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
358 if (ieee_flags != 0)
359 DFP_HANDLE_EXCEPTIONS (ieee_flags);
362 #if defined (L_sd_to_dd)
363 /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
364 _Decimal64
365 DFP_TO_DFP (_Decimal32 f_from)
367 union { _Decimal32 c; decSingle f; } from;
368 union { _Decimal64 c; decDouble f; } to;
370 from.c = f_from;
371 to.f = *decSingleToWider (&from.f, &to.f);
372 return to.c;
374 #endif
376 #if defined (L_sd_to_td)
377 /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
378 _Decimal128
379 DFP_TO_DFP (_Decimal32 f_from)
381 union { _Decimal32 c; decSingle f; } from;
382 union { _Decimal128 c; decQuad f; } to;
383 decDouble temp;
385 from.c = f_from;
386 temp = *decSingleToWider (&from.f, &temp);
387 to.f = *decDoubleToWider (&temp, &to.f);
388 return to.c;
390 #endif
392 #if defined (L_dd_to_td)
393 /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
394 _Decimal128
395 DFP_TO_DFP (_Decimal64 f_from)
397 union { _Decimal64 c; decDouble f; } from;
398 union { _Decimal128 c; decQuad f; } to;
400 from.c = f_from;
401 to.f = *decDoubleToWider (&from.f, &to.f);
402 return to.c;
404 #endif
406 #if defined (L_dd_to_sd)
407 /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
408 _Decimal32
409 DFP_TO_DFP (_Decimal64 f_from)
411 union { _Decimal32 c; decSingle f; } to;
412 union { _Decimal64 c; decDouble f; } from;
413 decContext context;
415 decContextDefault (&context, CONTEXT_INIT);
416 DFP_INIT_ROUNDMODE (context.round);
417 from.c = f_from;
418 to.f = *decSingleFromWider (&to.f, &from.f, &context);
419 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
420 dfp_conversion_exceptions (context.status);
421 return to.c;
423 #endif
425 #if defined (L_td_to_sd)
426 /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
427 _Decimal32
428 DFP_TO_DFP (_Decimal128 f_from)
430 union { _Decimal32 c; decSingle f; } to;
431 union { _Decimal128 c; decQuad f; } from;
432 decDouble temp;
433 decContext context;
435 decContextDefault (&context, CONTEXT_INIT);
436 DFP_INIT_ROUNDMODE (context.round);
437 from.c = f_from;
438 temp = *decDoubleFromWider (&temp, &from.f, &context);
439 to.f = *decSingleFromWider (&to.f, &temp, &context);
440 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
441 dfp_conversion_exceptions (context.status);
442 return to.c;
444 #endif
446 #if defined (L_td_to_dd)
447 /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
448 _Decimal64
449 DFP_TO_DFP (_Decimal128 f_from)
451 union { _Decimal64 c; decDouble f; } to;
452 union { _Decimal128 c; decQuad f; } from;
453 decContext context;
455 decContextDefault (&context, CONTEXT_INIT);
456 DFP_INIT_ROUNDMODE (context.round);
457 from.c = f_from;
458 to.f = *decDoubleFromWider (&to.f, &from.f, &context);
459 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
460 dfp_conversion_exceptions (context.status);
461 return to.c;
463 #endif
465 #if defined (L_dd_to_si) || defined (L_td_to_si) \
466 || defined (L_dd_to_usi) || defined (L_td_to_usi)
467 /* Use decNumber to convert directly from decimal float to integer types. */
468 INT_TYPE
469 DFP_TO_INT (DFP_C_TYPE x)
471 union { DFP_C_TYPE c; decFloat f; } u;
472 decContext context;
473 INT_TYPE i;
475 decContextDefault (&context, DEC_INIT_DECIMAL128);
476 context.round = DEC_ROUND_DOWN;
477 u.c = x;
478 i = DEC_FLOAT_TO_INT (&u.f, &context, context.round);
479 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
480 dfp_conversion_exceptions (context.status);
481 return i;
483 #endif
485 #if defined (L_sd_to_si) || (L_sd_to_usi)
486 /* Use decNumber to convert directly from decimal float to integer types. */
487 INT_TYPE
488 DFP_TO_INT (_Decimal32 x)
490 union { _Decimal32 c; decSingle f; } u32;
491 decDouble f64;
492 decContext context;
493 INT_TYPE i;
495 decContextDefault (&context, DEC_INIT_DECIMAL128);
496 context.round = DEC_ROUND_DOWN;
497 u32.c = x;
498 f64 = *decSingleToWider (&u32.f, &f64);
499 i = DEC_FLOAT_TO_INT (&f64, &context, context.round);
500 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
501 dfp_conversion_exceptions (context.status);
502 return i;
504 #endif
506 #if defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
507 || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
508 /* decNumber doesn't provide support for conversions to 64-bit integer
509 types, so do it the hard way. */
510 INT_TYPE
511 DFP_TO_INT (DFP_C_TYPE x)
513 /* decNumber's decimal* types have the same format as C's _Decimal*
514 types, but they have different calling conventions. */
516 /* TODO: Decimal float to integer conversions should raise FE_INVALID
517 if the result value does not fit into the result type. */
519 IEEE_TYPE s;
520 char buf[BUFMAX];
521 char *pos;
522 decNumber qval, n1, n2;
523 decContext context;
525 /* Use a large context to avoid losing precision. */
526 decContextDefault (&context, DEC_INIT_DECIMAL128);
527 /* Need non-default rounding mode here. */
528 context.round = DEC_ROUND_DOWN;
530 HOST_TO_IEEE (x, &s);
531 TO_INTERNAL (&s, &n1);
532 /* Rescale if the exponent is less than zero. */
533 decNumberToIntegralValue (&n2, &n1, &context);
534 /* Get a value to use for the quantize call. */
535 decNumberFromString (&qval, "1.", &context);
536 /* Force the exponent to zero. */
537 decNumberQuantize (&n1, &n2, &qval, &context);
538 /* Get a string, which at this point will not include an exponent. */
539 decNumberToString (&n1, buf);
540 /* Ignore the fractional part. */
541 pos = strchr (buf, '.');
542 if (pos)
543 *pos = 0;
544 /* Use a C library function to convert to the integral type. */
545 return STR_TO_INT (buf, NULL, 10);
547 #endif
549 #if defined (L_si_to_dd) || defined (L_si_to_td) \
550 || defined (L_usi_to_dd) || defined (L_usi_to_td)
551 /* Use decNumber to convert directly from integer to decimal float types. */
552 DFP_C_TYPE
553 INT_TO_DFP (INT_TYPE i)
555 union { DFP_C_TYPE c; decFloat f; } u;
557 u.f = *DEC_FLOAT_FROM_INT (&u.f, i);
558 return u.c;
560 #endif
562 #if defined (L_si_to_sd) || defined (L_usi_to_sd)
563 _Decimal32
564 /* Use decNumber to convert directly from integer to decimal float types. */
565 INT_TO_DFP (INT_TYPE i)
567 union { _Decimal32 c; decSingle f; } u32;
568 decDouble f64;
569 decContext context;
571 decContextDefault (&context, DEC_INIT_DECIMAL128);
572 f64 = *DEC_FLOAT_FROM_INT (&f64, i);
573 u32.f = *decSingleFromWider (&u32.f, &f64, &context);
574 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
575 dfp_conversion_exceptions (context.status);
576 return u32.c;
578 #endif
580 #if defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
581 || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
582 /* decNumber doesn't provide support for conversions from 64-bit integer
583 types, so do it the hard way. */
584 DFP_C_TYPE
585 INT_TO_DFP (INT_TYPE i)
587 DFP_C_TYPE f;
588 IEEE_TYPE s;
589 char buf[BUFMAX];
590 decContext context;
592 decContextDefault (&context, CONTEXT_INIT);
593 DFP_INIT_ROUNDMODE (context.round);
595 /* Use a C library function to get a floating point string. */
596 sprintf (buf, INT_FMT ".", CAST_FOR_FMT(i));
597 /* Convert from the floating point string to a decimal* type. */
598 FROM_STRING (&s, buf, &context);
599 IEEE_TO_HOST (s, &f);
601 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
602 dfp_conversion_exceptions (context.status);
604 return f;
606 #endif
608 #if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
609 || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
610 || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
611 && LONG_DOUBLE_HAS_XF_MODE) \
612 || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
613 && LONG_DOUBLE_HAS_TF_MODE)
614 BFP_TYPE
615 DFP_TO_BFP (DFP_C_TYPE f)
617 IEEE_TYPE s;
618 char buf[BUFMAX];
620 HOST_TO_IEEE (f, &s);
621 /* Write the value to a string. */
622 TO_STRING (&s, buf);
623 /* Read it as the binary floating point type and return that. */
624 return STR_TO_BFP (buf, NULL);
626 #endif
628 #if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
629 || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
630 || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
631 && LONG_DOUBLE_HAS_XF_MODE) \
632 || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
633 && LONG_DOUBLE_HAS_TF_MODE)
634 DFP_C_TYPE
635 BFP_TO_DFP (BFP_TYPE x)
637 DFP_C_TYPE f;
638 IEEE_TYPE s;
639 char buf[BUFMAX];
640 decContext context;
642 decContextDefault (&context, CONTEXT_INIT);
643 DFP_INIT_ROUNDMODE (context.round);
645 /* Use a C library function to write the floating point value to a string. */
646 sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
648 /* Convert from the floating point string to a decimal* type. */
649 FROM_STRING (&s, buf, &context);
650 IEEE_TO_HOST (s, &f);
652 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
654 /* decNumber exception flags we care about here. */
655 int ieee_flags;
656 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
657 | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
658 dec_flags &= context.status;
659 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
660 if (ieee_flags != 0)
661 DFP_HANDLE_EXCEPTIONS (ieee_flags);
664 return f;
666 #endif
668 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
669 CMPtype
670 DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
672 decNumber arg1, arg2;
673 IEEE_TYPE a, b;
675 HOST_TO_IEEE (arg_a, &a);
676 HOST_TO_IEEE (arg_b, &b);
677 TO_INTERNAL (&a, &arg1);
678 TO_INTERNAL (&b, &arg2);
679 return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
681 #endif /* L_unord_sd || L_unord_dd || L_unord_td */