libstdc++: Check string value_type in std::make_format_args [PR112607]
[official-gcc.git] / libgcc / dfp-bit.c
blob8c0f543f52c3408f5c05ce4cb600342f1469b261
1 /* This is a software decimal floating point library.
2 Copyright (C) 2005-2023 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 3, or (at your option) any later
9 version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 /* This implements IEEE 754 decimal floating point arithmetic, but
26 does not provide a mechanism for setting the rounding mode, or for
27 generating or handling exceptions. Conversions between decimal
28 floating point types and other types depend on C library functions.
30 Contributed by Ben Elliston <bje@au.ibm.com>. */
32 #include <stdio.h>
33 #include <stdlib.h>
34 /* FIXME: compile with -std=gnu99 to get these from stdlib.h */
35 extern float strtof (const char *, char **);
36 extern long double strtold (const char *, char **);
37 #include <string.h>
38 #include <limits.h>
40 #include "dfp-bit.h"
42 /* Forward declarations. */
43 #if WIDTH == 32 || WIDTH_TO == 32
44 void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
45 void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
46 #endif
47 #if WIDTH == 64 || WIDTH_TO == 64
48 void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
49 void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
50 #endif
51 #if WIDTH == 128 || WIDTH_TO == 128
52 void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
53 void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
54 #endif
56 /* A pointer to a binary decFloat operation. */
57 typedef decFloat* (*dfp_binary_func)
58 (decFloat *, const decFloat *, const decFloat *, decContext *);
60 /* Binary operations. */
62 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
63 binary operation. */
64 static inline decFloat
65 dfp_binary_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
67 decFloat result;
68 decContext context;
70 decContextDefault (&context, CONTEXT_INIT);
71 DFP_INIT_ROUNDMODE (context.round);
73 /* Perform the operation. */
74 op (&result, &arg_a, &arg_b, &context);
76 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
78 /* decNumber exception flags we care about here. */
79 int ieee_flags;
80 int dec_flags = DEC_IEEE_854_Division_by_zero | DEC_IEEE_854_Inexact
81 | DEC_IEEE_854_Invalid_operation | DEC_IEEE_854_Overflow
82 | DEC_IEEE_854_Underflow;
83 dec_flags &= context.status;
84 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
85 if (ieee_flags != 0)
86 DFP_HANDLE_EXCEPTIONS (ieee_flags);
89 return result;
92 #if WIDTH == 32
93 /* The decNumber package doesn't provide arithmetic for decSingle (32 bits);
94 convert to decDouble, use the operation for that, and convert back. */
95 static inline _Decimal32
96 d32_binary_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
98 union { _Decimal32 c; decSingle f; } a32, b32, res32;
99 decDouble a, b, res;
100 decContext context;
102 /* Widen the operands and perform the operation. */
103 a32.c = arg_a;
104 b32.c = arg_b;
105 decSingleToWider (&a32.f, &a);
106 decSingleToWider (&b32.f, &b);
107 res = dfp_binary_op (op, a, b);
109 /* Narrow the result, which might result in an underflow or overflow. */
110 decContextDefault (&context, CONTEXT_INIT);
111 DFP_INIT_ROUNDMODE (context.round);
112 decSingleFromWider (&res32.f, &res, &context);
113 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
115 /* decNumber exception flags we care about here. */
116 int ieee_flags;
117 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Overflow
118 | DEC_IEEE_854_Underflow;
119 dec_flags &= context.status;
120 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
121 if (ieee_flags != 0)
122 DFP_HANDLE_EXCEPTIONS (ieee_flags);
125 return res32.c;
127 #else
128 /* decFloat operations are supported for decDouble (64 bits) and
129 decQuad (128 bits). The bit patterns for the types are the same. */
130 static inline DFP_C_TYPE
131 dnn_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
133 union { DFP_C_TYPE c; decFloat f; } a, b, result;
135 a.c = arg_a;
136 b.c = arg_b;
137 result.f = dfp_binary_op (op, a.f, b.f);
138 return result.c;
140 #endif
142 /* Comparison operations. */
144 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
145 comparison. */
146 static inline CMPtype
147 dfp_compare_op (dfp_binary_func op, decFloat arg_a, decFloat arg_b)
149 decContext context;
150 decFloat res;
151 int result;
153 decContextDefault (&context, CONTEXT_INIT);
154 DFP_INIT_ROUNDMODE (context.round);
156 /* Perform the comparison. */
157 op (&res, &arg_a, &arg_b, &context);
159 if (DEC_FLOAT_IS_SIGNED (&res))
160 result = -1;
161 else if (DEC_FLOAT_IS_ZERO (&res))
162 result = 0;
163 else if (DEC_FLOAT_IS_NAN (&res))
164 result = -2;
165 else
166 result = 1;
168 return (CMPtype) result;
171 #if WIDTH == 32
172 /* The decNumber package doesn't provide comparisons for decSingle (32 bits);
173 convert to decDouble, use the operation for that, and convert back. */
174 static inline CMPtype
175 d32_compare_op (dfp_binary_func op, _Decimal32 arg_a, _Decimal32 arg_b)
177 union { _Decimal32 c; decSingle f; } a32, b32;
178 decDouble a, b;
180 a32.c = arg_a;
181 b32.c = arg_b;
182 decSingleToWider (&a32.f, &a);
183 decSingleToWider (&b32.f, &b);
184 return dfp_compare_op (op, a, b);
186 #else
187 /* decFloat comparisons are supported for decDouble (64 bits) and
188 decQuad (128 bits). The bit patterns for the types are the same. */
189 static inline CMPtype
190 dnn_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
192 union { DFP_C_TYPE c; decFloat f; } a, b;
194 a.c = arg_a;
195 b.c = arg_b;
196 return dfp_compare_op (op, a.f, b.f);
198 #endif
200 #if defined(L_conv_sd)
201 void
202 __host_to_ieee_32 (_Decimal32 in, decimal32 *out)
204 memcpy (out, &in, 4);
207 void
208 __ieee_to_host_32 (decimal32 in, _Decimal32 *out)
210 memcpy (out, &in, 4);
212 #endif /* L_conv_sd */
214 #if defined(L_conv_dd)
215 void
216 __host_to_ieee_64 (_Decimal64 in, decimal64 *out)
218 memcpy (out, &in, 8);
221 void
222 __ieee_to_host_64 (decimal64 in, _Decimal64 *out)
224 memcpy (out, &in, 8);
226 #endif /* L_conv_dd */
228 #if defined(L_conv_td)
229 void
230 __host_to_ieee_128 (_Decimal128 in, decimal128 *out)
232 memcpy (out, &in, 16);
235 void
236 __ieee_to_host_128 (decimal128 in, _Decimal128 *out)
238 memcpy (out, &in, 16);
240 #endif /* L_conv_td */
242 #if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
243 DFP_C_TYPE
244 DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
246 return DFP_BINARY_OP (DEC_FLOAT_ADD, arg_a, arg_b);
249 DFP_C_TYPE
250 DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
252 return DFP_BINARY_OP (DEC_FLOAT_SUBTRACT, arg_a, arg_b);
254 #endif /* L_addsub */
256 #if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
257 DFP_C_TYPE
258 DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
260 return DFP_BINARY_OP (DEC_FLOAT_MULTIPLY, arg_a, arg_b);
262 #endif /* L_mul */
264 #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
265 DFP_C_TYPE
266 DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
268 return DFP_BINARY_OP (DEC_FLOAT_DIVIDE, arg_a, arg_b);
270 #endif /* L_div */
272 #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
273 CMPtype
274 DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
276 CMPtype stat;
277 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
278 /* For EQ return zero for true, nonzero for false. */
279 return stat != 0;
281 #endif /* L_eq */
283 #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
284 CMPtype
285 DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
287 int stat;
288 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
289 /* For NE return zero for true, nonzero for false. */
290 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
291 return 1;
292 return stat != 0;
294 #endif /* L_ne */
296 #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
297 CMPtype
298 DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
300 int stat;
301 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
302 /* For LT return -1 (<0) for true, 1 for false. */
303 return (stat == -1) ? -1 : 1;
305 #endif /* L_lt */
307 #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
308 CMPtype
309 DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
311 int stat;
312 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
313 /* For GT return 1 (>0) for true, -1 for false. */
314 return (stat == 1) ? 1 : -1;
316 #endif
318 #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
319 CMPtype
320 DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
322 int stat;
323 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
324 /* For LE return 0 (<= 0) for true, 1 for false. */
325 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
326 return 1;
327 return stat == 1;
329 #endif /* L_le */
331 #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
332 CMPtype
333 DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
335 int stat;
336 stat = DFP_COMPARE_OP (DEC_FLOAT_COMPARE, arg_a, arg_b);
337 /* For GE return 1 (>=0) for true, -1 for false. */
338 if (__builtin_expect (stat == -2, 0)) /* An operand is NaN. */
339 return -1;
340 return (stat != -1) ? 1 : -1;
342 #endif /* L_ge */
344 #define BUFMAX 128
346 /* Check for floating point exceptions that are relevant for conversions
347 between decimal float values and handle them. */
348 static inline void
349 dfp_conversion_exceptions (const int status)
351 /* decNumber exception flags we care about here. */
352 int ieee_flags;
353 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
354 | DEC_IEEE_854_Overflow;
355 dec_flags &= status;
356 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
357 if (ieee_flags != 0)
358 DFP_HANDLE_EXCEPTIONS (ieee_flags);
361 #if defined (L_sd_to_dd)
362 /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
363 _Decimal64
364 DFP_TO_DFP (_Decimal32 f_from)
366 union { _Decimal32 c; decSingle f; } from;
367 union { _Decimal64 c; decDouble f; } to;
369 from.c = f_from;
370 to.f = *decSingleToWider (&from.f, &to.f);
371 return to.c;
373 #endif
375 #if defined (L_sd_to_td)
376 /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
377 _Decimal128
378 DFP_TO_DFP (_Decimal32 f_from)
380 union { _Decimal32 c; decSingle f; } from;
381 union { _Decimal128 c; decQuad f; } to;
382 decDouble temp;
384 from.c = f_from;
385 temp = *decSingleToWider (&from.f, &temp);
386 to.f = *decDoubleToWider (&temp, &to.f);
387 return to.c;
389 #endif
391 #if defined (L_dd_to_td)
392 /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
393 _Decimal128
394 DFP_TO_DFP (_Decimal64 f_from)
396 union { _Decimal64 c; decDouble f; } from;
397 union { _Decimal128 c; decQuad f; } to;
399 from.c = f_from;
400 to.f = *decDoubleToWider (&from.f, &to.f);
401 return to.c;
403 #endif
405 #if defined (L_dd_to_sd)
406 /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
407 _Decimal32
408 DFP_TO_DFP (_Decimal64 f_from)
410 union { _Decimal32 c; decSingle f; } to;
411 union { _Decimal64 c; decDouble f; } from;
412 decContext context;
414 decContextDefault (&context, CONTEXT_INIT);
415 DFP_INIT_ROUNDMODE (context.round);
416 from.c = f_from;
417 to.f = *decSingleFromWider (&to.f, &from.f, &context);
418 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
419 dfp_conversion_exceptions (context.status);
420 return to.c;
422 #endif
424 #if defined (L_td_to_sd)
425 /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
426 _Decimal32
427 DFP_TO_DFP (_Decimal128 f_from)
429 union { _Decimal32 c; decSingle f; } to;
430 union { _Decimal128 c; decQuad f; } from;
431 decDouble temp;
432 decContext context;
434 decContextDefault (&context, CONTEXT_INIT);
435 DFP_INIT_ROUNDMODE (context.round);
436 from.c = f_from;
437 temp = *decDoubleFromWider (&temp, &from.f, &context);
438 to.f = *decSingleFromWider (&to.f, &temp, &context);
439 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
440 dfp_conversion_exceptions (context.status);
441 return to.c;
443 #endif
445 #if defined (L_td_to_dd)
446 /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
447 _Decimal64
448 DFP_TO_DFP (_Decimal128 f_from)
450 union { _Decimal64 c; decDouble f; } to;
451 union { _Decimal128 c; decQuad f; } from;
452 decContext context;
454 decContextDefault (&context, CONTEXT_INIT);
455 DFP_INIT_ROUNDMODE (context.round);
456 from.c = f_from;
457 to.f = *decDoubleFromWider (&to.f, &from.f, &context);
458 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
459 dfp_conversion_exceptions (context.status);
460 return to.c;
462 #endif
464 #if defined (L_dd_to_si) || defined (L_td_to_si) \
465 || defined (L_dd_to_usi) || defined (L_td_to_usi)
466 /* Use decNumber to convert directly from decimal float to integer types. */
467 INT_TYPE
468 DFP_TO_INT (DFP_C_TYPE x)
470 union { DFP_C_TYPE c; decFloat f; } u;
471 decContext context;
472 INT_TYPE i;
474 decContextDefault (&context, DEC_INIT_DECIMAL128);
475 context.round = DEC_ROUND_DOWN;
476 u.c = x;
477 i = DEC_FLOAT_TO_INT (&u.f, &context, context.round);
478 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
479 dfp_conversion_exceptions (context.status);
480 return i;
482 #endif
484 #if defined (L_sd_to_si) || (L_sd_to_usi)
485 /* Use decNumber to convert directly from decimal float to integer types. */
486 INT_TYPE
487 DFP_TO_INT (_Decimal32 x)
489 union { _Decimal32 c; decSingle f; } u32;
490 decDouble f64;
491 decContext context;
492 INT_TYPE i;
494 decContextDefault (&context, DEC_INIT_DECIMAL128);
495 context.round = DEC_ROUND_DOWN;
496 u32.c = x;
497 f64 = *decSingleToWider (&u32.f, &f64);
498 i = DEC_FLOAT_TO_INT (&f64, &context, context.round);
499 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
500 dfp_conversion_exceptions (context.status);
501 return i;
503 #endif
505 #if defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
506 || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
507 /* decNumber doesn't provide support for conversions to 64-bit integer
508 types, so do it the hard way. */
509 INT_TYPE
510 DFP_TO_INT (DFP_C_TYPE x)
512 /* decNumber's decimal* types have the same format as C's _Decimal*
513 types, but they have different calling conventions. */
515 /* TODO: Decimal float to integer conversions should raise FE_INVALID
516 if the result value does not fit into the result type. */
518 IEEE_TYPE s;
519 char buf[BUFMAX];
520 char *pos;
521 decNumber qval, n1, n2;
522 decContext context;
524 /* Use a large context to avoid losing precision. */
525 decContextDefault (&context, DEC_INIT_DECIMAL128);
526 /* Need non-default rounding mode here. */
527 context.round = DEC_ROUND_DOWN;
529 HOST_TO_IEEE (x, &s);
530 TO_INTERNAL (&s, &n1);
531 /* Rescale if the exponent is less than zero. */
532 decNumberToIntegralValue (&n2, &n1, &context);
533 /* Get a value to use for the quantize call. */
534 decNumberFromString (&qval, "1.", &context);
535 /* Force the exponent to zero. */
536 decNumberQuantize (&n1, &n2, &qval, &context);
537 /* Get a string, which at this point will not include an exponent. */
538 decNumberToString (&n1, buf);
539 /* Ignore the fractional part. */
540 pos = strchr (buf, '.');
541 if (pos)
542 *pos = 0;
543 /* Use a C library function to convert to the integral type. */
544 return STR_TO_INT (buf, NULL, 10);
546 #endif
548 #if defined (L_si_to_dd) || defined (L_si_to_td) \
549 || defined (L_usi_to_dd) || defined (L_usi_to_td)
550 /* Use decNumber to convert directly from integer to decimal float types. */
551 DFP_C_TYPE
552 INT_TO_DFP (INT_TYPE i)
554 union { DFP_C_TYPE c; decFloat f; } u;
556 u.f = *DEC_FLOAT_FROM_INT (&u.f, i);
557 return u.c;
559 #endif
561 #if defined (L_si_to_sd) || defined (L_usi_to_sd)
562 _Decimal32
563 /* Use decNumber to convert directly from integer to decimal float types. */
564 INT_TO_DFP (INT_TYPE i)
566 union { _Decimal32 c; decSingle f; } u32;
567 decDouble f64;
568 decContext context;
570 decContextDefault (&context, DEC_INIT_DECIMAL128);
571 f64 = *DEC_FLOAT_FROM_INT (&f64, i);
572 u32.f = *decSingleFromWider (&u32.f, &f64, &context);
573 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
574 dfp_conversion_exceptions (context.status);
575 return u32.c;
577 #endif
579 #if defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
580 || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
581 /* decNumber doesn't provide support for conversions from 64-bit integer
582 types, so do it the hard way. */
583 DFP_C_TYPE
584 INT_TO_DFP (INT_TYPE i)
586 DFP_C_TYPE f;
587 IEEE_TYPE s;
588 char buf[BUFMAX];
589 decContext context;
591 decContextDefault (&context, CONTEXT_INIT);
592 DFP_INIT_ROUNDMODE (context.round);
594 /* Use a C library function to get a floating point string. */
595 sprintf (buf, INT_FMT ".", CAST_FOR_FMT(i));
596 /* Convert from the floating point string to a decimal* type. */
597 FROM_STRING (&s, buf, &context);
598 IEEE_TO_HOST (s, &f);
600 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
601 dfp_conversion_exceptions (context.status);
603 return f;
605 #endif
607 #if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
608 || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
609 || defined (L_sd_to_kf) || defined (L_dd_to_kf) || defined (L_td_to_kf) \
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_kf_to_sd) || defined (L_kf_to_dd) || defined (L_kf_to_td) \
631 || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
632 && LONG_DOUBLE_HAS_XF_MODE) \
633 || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
634 && LONG_DOUBLE_HAS_TF_MODE)
635 DFP_C_TYPE
636 BFP_TO_DFP (BFP_TYPE x)
638 DFP_C_TYPE f;
639 IEEE_TYPE s;
640 char buf[BUFMAX];
641 decContext context;
643 decContextDefault (&context, CONTEXT_INIT);
644 DFP_INIT_ROUNDMODE (context.round);
646 /* Use the sprintf library function to write the floating point value to a
647 string.
649 If we are handling the IEEE 128-bit floating point on PowerPC, use the
650 special function __sprintfkf instead of sprintf. This function allows us
651 to use __sprintfieee128 if we have a new enough GLIBC, and it can fall back
652 to using the traditional sprintf via conversion to IBM 128-bit if the glibc
653 is older. */
654 BFP_SPRINTF (buf, BFP_FMT, (BFP_VIA_TYPE) x);
656 /* Convert from the floating point string to a decimal* type. */
657 FROM_STRING (&s, buf, &context);
658 IEEE_TO_HOST (s, &f);
660 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
662 /* decNumber exception flags we care about here. */
663 int ieee_flags;
664 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
665 | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
666 dec_flags &= context.status;
667 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
668 if (ieee_flags != 0)
669 DFP_HANDLE_EXCEPTIONS (ieee_flags);
672 return f;
674 #endif
676 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
677 CMPtype
678 DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
680 decNumber arg1, arg2;
681 IEEE_TYPE a, b;
683 HOST_TO_IEEE (arg_a, &a);
684 HOST_TO_IEEE (arg_b, &b);
685 TO_INTERNAL (&a, &arg1);
686 TO_INTERNAL (&b, &arg2);
687 return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
689 #endif /* L_unord_sd || L_unord_dd || L_unord_td */