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
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
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>. */
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 **);
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
);
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
);
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
);
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
65 static inline decFloat
66 dfp_binary_op (dfp_binary_func op
, decFloat arg_a
, decFloat arg_b
)
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. */
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
);
87 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
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
;
103 /* Widen the operands and perform the operation. */
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. */
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
);
123 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
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
;
138 result
.f
= dfp_binary_op (op
, a
.f
, b
.f
);
143 /* Comparison operations. */
145 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
147 static inline CMPtype
148 dfp_compare_op (dfp_binary_func op
, decFloat arg_a
, decFloat arg_b
)
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
))
162 else if (DEC_FLOAT_IS_ZERO (&res
))
164 else if (DEC_FLOAT_IS_NAN (&res
))
169 return (CMPtype
) result
;
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
;
183 decSingleToWider (&a32
.f
, &a
);
184 decSingleToWider (&b32
.f
, &b
);
185 return dfp_compare_op (op
, a
, b
);
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
;
197 return dfp_compare_op (op
, a
.f
, b
.f
);
201 #if defined(L_conv_sd)
203 __host_to_ieee_32 (_Decimal32 in
, decimal32
*out
)
205 memcpy (out
, &in
, 4);
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)
217 __host_to_ieee_64 (_Decimal64 in
, decimal64
*out
)
219 memcpy (out
, &in
, 8);
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)
231 __host_to_ieee_128 (_Decimal128 in
, decimal128
*out
)
233 memcpy (out
, &in
, 16);
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)
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
);
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)
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
);
265 #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
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
);
273 #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
275 DFP_EQ (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
278 stat
= DFP_COMPARE_OP (DEC_FLOAT_COMPARE
, arg_a
, arg_b
);
279 /* For EQ return zero for true, nonzero for false. */
284 #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
286 DFP_NE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
297 #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
299 DFP_LT (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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;
308 #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
310 DFP_GT (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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;
319 #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
321 DFP_LE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
332 #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
334 DFP_GE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
341 return (stat
!= -1) ? 1 : -1;
347 /* Check for floating point exceptions that are relevant for conversions
348 between decimal float values and handle them. */
350 dfp_conversion_exceptions (const int status
)
352 /* decNumber exception flags we care about here. */
354 int dec_flags
= DEC_IEEE_854_Inexact
| DEC_IEEE_854_Invalid_operation
355 | DEC_IEEE_854_Overflow
;
357 ieee_flags
= DFP_IEEE_FLAGS (dec_flags
);
359 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
362 #if defined (L_sd_to_dd)
363 /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
365 DFP_TO_DFP (_Decimal32 f_from
)
367 union { _Decimal32 c
; decSingle f
; } from
;
368 union { _Decimal64 c
; decDouble f
; } to
;
371 to
.f
= *decSingleToWider (&from
.f
, &to
.f
);
376 #if defined (L_sd_to_td)
377 /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
379 DFP_TO_DFP (_Decimal32 f_from
)
381 union { _Decimal32 c
; decSingle f
; } from
;
382 union { _Decimal128 c
; decQuad f
; } to
;
386 temp
= *decSingleToWider (&from
.f
, &temp
);
387 to
.f
= *decDoubleToWider (&temp
, &to
.f
);
392 #if defined (L_dd_to_td)
393 /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
395 DFP_TO_DFP (_Decimal64 f_from
)
397 union { _Decimal64 c
; decDouble f
; } from
;
398 union { _Decimal128 c
; decQuad f
; } to
;
401 to
.f
= *decDoubleToWider (&from
.f
, &to
.f
);
406 #if defined (L_dd_to_sd)
407 /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
409 DFP_TO_DFP (_Decimal64 f_from
)
411 union { _Decimal32 c
; decSingle f
; } to
;
412 union { _Decimal64 c
; decDouble f
; } from
;
415 decContextDefault (&context
, CONTEXT_INIT
);
416 DFP_INIT_ROUNDMODE (context
.round
);
418 to
.f
= *decSingleFromWider (&to
.f
, &from
.f
, &context
);
419 if (DFP_EXCEPTIONS_ENABLED
&& context
.status
!= 0)
420 dfp_conversion_exceptions (context
.status
);
425 #if defined (L_td_to_sd)
426 /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
428 DFP_TO_DFP (_Decimal128 f_from
)
430 union { _Decimal32 c
; decSingle f
; } to
;
431 union { _Decimal128 c
; decQuad f
; } from
;
435 decContextDefault (&context
, CONTEXT_INIT
);
436 DFP_INIT_ROUNDMODE (context
.round
);
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
);
446 #if defined (L_td_to_dd)
447 /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
449 DFP_TO_DFP (_Decimal128 f_from
)
451 union { _Decimal64 c
; decDouble f
; } to
;
452 union { _Decimal128 c
; decQuad f
; } from
;
455 decContextDefault (&context
, CONTEXT_INIT
);
456 DFP_INIT_ROUNDMODE (context
.round
);
458 to
.f
= *decDoubleFromWider (&to
.f
, &from
.f
, &context
);
459 if (DFP_EXCEPTIONS_ENABLED
&& context
.status
!= 0)
460 dfp_conversion_exceptions (context
.status
);
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. */
469 DFP_TO_INT (DFP_C_TYPE x
)
471 union { DFP_C_TYPE c
; decFloat f
; } u
;
475 decContextDefault (&context
, DEC_INIT_DECIMAL128
);
476 context
.round
= DEC_ROUND_DOWN
;
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
);
485 #if defined (L_sd_to_si) || (L_sd_to_usi)
486 /* Use decNumber to convert directly from decimal float to integer types. */
488 DFP_TO_INT (_Decimal32 x
)
490 union { _Decimal32 c
; decSingle f
; } u32
;
495 decContextDefault (&context
, DEC_INIT_DECIMAL128
);
496 context
.round
= DEC_ROUND_DOWN
;
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
);
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. */
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. */
522 decNumber qval
, n1
, n2
;
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
, '.');
544 /* Use a C library function to convert to the integral type. */
545 return STR_TO_INT (buf
, NULL
, 10);
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. */
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
);
562 #if defined (L_si_to_sd) || defined (L_usi_to_sd)
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
;
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
);
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. */
585 INT_TO_DFP (INT_TYPE i
)
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
);
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)
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_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)
635 BFP_TO_DFP (BFP_TYPE x
)
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. */
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
);
661 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
668 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
670 DFP_UNORD (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
672 decNumber arg1
, arg2
;
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 */