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
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
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>. */
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 **);
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
);
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
);
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
);
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
64 static inline decFloat
65 dfp_binary_op (dfp_binary_func op
, decFloat arg_a
, decFloat arg_b
)
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. */
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
);
86 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
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
;
102 /* Widen the operands and perform the operation. */
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. */
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
);
122 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
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
;
137 result
.f
= dfp_binary_op (op
, a
.f
, b
.f
);
142 /* Comparison operations. */
144 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
146 static inline CMPtype
147 dfp_compare_op (dfp_binary_func op
, decFloat arg_a
, decFloat arg_b
)
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
))
161 else if (DEC_FLOAT_IS_ZERO (&res
))
163 else if (DEC_FLOAT_IS_NAN (&res
))
168 return (CMPtype
) result
;
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
;
182 decSingleToWider (&a32
.f
, &a
);
183 decSingleToWider (&b32
.f
, &b
);
184 return dfp_compare_op (op
, a
, b
);
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
;
196 return dfp_compare_op (op
, a
.f
, b
.f
);
200 #if defined(L_conv_sd)
202 __host_to_ieee_32 (_Decimal32 in
, decimal32
*out
)
204 memcpy (out
, &in
, 4);
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)
216 __host_to_ieee_64 (_Decimal64 in
, decimal64
*out
)
218 memcpy (out
, &in
, 8);
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)
230 __host_to_ieee_128 (_Decimal128 in
, decimal128
*out
)
232 memcpy (out
, &in
, 16);
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)
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
);
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)
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
);
264 #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
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
);
272 #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
274 DFP_EQ (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
277 stat
= DFP_COMPARE_OP (DEC_FLOAT_COMPARE
, arg_a
, arg_b
);
278 /* For EQ return zero for true, nonzero for false. */
283 #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
285 DFP_NE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
296 #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
298 DFP_LT (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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;
307 #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
309 DFP_GT (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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;
318 #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
320 DFP_LE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
331 #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
333 DFP_GE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
340 return (stat
!= -1) ? 1 : -1;
346 /* Check for floating point exceptions that are relevant for conversions
347 between decimal float values and handle them. */
349 dfp_conversion_exceptions (const int status
)
351 /* decNumber exception flags we care about here. */
353 int dec_flags
= DEC_IEEE_854_Inexact
| DEC_IEEE_854_Invalid_operation
354 | DEC_IEEE_854_Overflow
;
356 ieee_flags
= DFP_IEEE_FLAGS (dec_flags
);
358 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
361 #if defined (L_sd_to_dd)
362 /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
364 DFP_TO_DFP (_Decimal32 f_from
)
366 union { _Decimal32 c
; decSingle f
; } from
;
367 union { _Decimal64 c
; decDouble f
; } to
;
370 to
.f
= *decSingleToWider (&from
.f
, &to
.f
);
375 #if defined (L_sd_to_td)
376 /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
378 DFP_TO_DFP (_Decimal32 f_from
)
380 union { _Decimal32 c
; decSingle f
; } from
;
381 union { _Decimal128 c
; decQuad f
; } to
;
385 temp
= *decSingleToWider (&from
.f
, &temp
);
386 to
.f
= *decDoubleToWider (&temp
, &to
.f
);
391 #if defined (L_dd_to_td)
392 /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
394 DFP_TO_DFP (_Decimal64 f_from
)
396 union { _Decimal64 c
; decDouble f
; } from
;
397 union { _Decimal128 c
; decQuad f
; } to
;
400 to
.f
= *decDoubleToWider (&from
.f
, &to
.f
);
405 #if defined (L_dd_to_sd)
406 /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
408 DFP_TO_DFP (_Decimal64 f_from
)
410 union { _Decimal32 c
; decSingle f
; } to
;
411 union { _Decimal64 c
; decDouble f
; } from
;
414 decContextDefault (&context
, CONTEXT_INIT
);
415 DFP_INIT_ROUNDMODE (context
.round
);
417 to
.f
= *decSingleFromWider (&to
.f
, &from
.f
, &context
);
418 if (DFP_EXCEPTIONS_ENABLED
&& context
.status
!= 0)
419 dfp_conversion_exceptions (context
.status
);
424 #if defined (L_td_to_sd)
425 /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
427 DFP_TO_DFP (_Decimal128 f_from
)
429 union { _Decimal32 c
; decSingle f
; } to
;
430 union { _Decimal128 c
; decQuad f
; } from
;
434 decContextDefault (&context
, CONTEXT_INIT
);
435 DFP_INIT_ROUNDMODE (context
.round
);
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
);
445 #if defined (L_td_to_dd)
446 /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
448 DFP_TO_DFP (_Decimal128 f_from
)
450 union { _Decimal64 c
; decDouble f
; } to
;
451 union { _Decimal128 c
; decQuad f
; } from
;
454 decContextDefault (&context
, CONTEXT_INIT
);
455 DFP_INIT_ROUNDMODE (context
.round
);
457 to
.f
= *decDoubleFromWider (&to
.f
, &from
.f
, &context
);
458 if (DFP_EXCEPTIONS_ENABLED
&& context
.status
!= 0)
459 dfp_conversion_exceptions (context
.status
);
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. */
468 DFP_TO_INT (DFP_C_TYPE x
)
470 union { DFP_C_TYPE c
; decFloat f
; } u
;
474 decContextDefault (&context
, DEC_INIT_DECIMAL128
);
475 context
.round
= DEC_ROUND_DOWN
;
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
);
484 #if defined (L_sd_to_si) || (L_sd_to_usi)
485 /* Use decNumber to convert directly from decimal float to integer types. */
487 DFP_TO_INT (_Decimal32 x
)
489 union { _Decimal32 c
; decSingle f
; } u32
;
494 decContextDefault (&context
, DEC_INIT_DECIMAL128
);
495 context
.round
= DEC_ROUND_DOWN
;
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
);
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. */
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. */
521 decNumber qval
, n1
, n2
;
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
, '.');
543 /* Use a C library function to convert to the integral type. */
544 return STR_TO_INT (buf
, NULL
, 10);
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. */
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
);
561 #if defined (L_si_to_sd) || defined (L_usi_to_sd)
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
;
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
);
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. */
584 INT_TO_DFP (INT_TYPE i
)
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
);
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)
615 DFP_TO_BFP (DFP_C_TYPE f
)
620 HOST_TO_IEEE (f
, &s
);
621 /* Write the value to a string. */
623 /* Read it as the binary floating point type and return that. */
624 return STR_TO_BFP (buf
, NULL
);
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)
636 BFP_TO_DFP (BFP_TYPE x
)
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
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
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. */
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
);
669 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
676 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
678 DFP_UNORD (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
680 decNumber arg1
, arg2
;
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 */