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
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
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
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
30 /* This implements IEEE 754 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>. */
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 **);
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
);
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
);
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
);
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
69 static inline decFloat
70 dfp_binary_op (dfp_binary_func op
, decFloat arg_a
, decFloat arg_b
)
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. */
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
);
91 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
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
;
107 /* Widen the operands and perform the operation. */
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. */
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
);
127 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
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
;
142 result
.f
= dfp_binary_op (op
, a
.f
, b
.f
);
147 /* Comparison operations. */
149 /* Use a decFloat (decDouble or decQuad) function to perform a DFP
151 static inline CMPtype
152 dfp_compare_op (dfp_binary_func op
, decFloat arg_a
, decFloat arg_b
)
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
))
166 else if (DEC_FLOAT_IS_ZERO (&res
))
168 else if (DEC_FLOAT_IS_NAN (&res
))
173 return (CMPtype
) result
;
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
;
187 decSingleToWider (&a32
.f
, &a
);
188 decSingleToWider (&b32
.f
, &b
);
189 return dfp_compare_op (op
, a
, b
);
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
;
201 return dfp_compare_op (op
, a
.f
, b
.f
);
205 #if defined(L_conv_sd)
207 __host_to_ieee_32 (_Decimal32 in
, decimal32
*out
)
209 memcpy (out
, &in
, 4);
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)
221 __host_to_ieee_64 (_Decimal64 in
, decimal64
*out
)
223 memcpy (out
, &in
, 8);
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)
235 __host_to_ieee_128 (_Decimal128 in
, decimal128
*out
)
237 memcpy (out
, &in
, 16);
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)
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
);
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)
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
);
269 #if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
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
);
277 #if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
279 DFP_EQ (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
282 stat
= DFP_COMPARE_OP (DEC_FLOAT_COMPARE
, arg_a
, arg_b
);
283 /* For EQ return zero for true, nonzero for false. */
288 #if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
290 DFP_NE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
301 #if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
303 DFP_LT (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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;
312 #if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
314 DFP_GT (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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;
323 #if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
325 DFP_LE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
336 #if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
338 DFP_GE (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
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. */
345 return (stat
!= -1) ? 1 : -1;
351 /* Check for floating point exceptions that are relevant for conversions
352 between decimal float values and handle them. */
354 dfp_conversion_exceptions (const int status
)
356 /* decNumber exception flags we care about here. */
358 int dec_flags
= DEC_IEEE_854_Inexact
| DEC_IEEE_854_Invalid_operation
359 | DEC_IEEE_854_Overflow
;
361 ieee_flags
= DFP_IEEE_FLAGS (dec_flags
);
363 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
366 #if defined (L_sd_to_dd)
367 /* Use decNumber to convert directly from _Decimal32 to _Decimal64. */
369 DFP_TO_DFP (_Decimal32 f_from
)
371 union { _Decimal32 c
; decSingle f
; } from
;
372 union { _Decimal64 c
; decDouble f
; } to
;
375 to
.f
= *decSingleToWider (&from
.f
, &to
.f
);
380 #if defined (L_sd_to_td)
381 /* Use decNumber to convert directly from _Decimal32 to _Decimal128. */
383 DFP_TO_DFP (_Decimal32 f_from
)
385 union { _Decimal32 c
; decSingle f
; } from
;
386 union { _Decimal128 c
; decQuad f
; } to
;
390 temp
= *decSingleToWider (&from
.f
, &temp
);
391 to
.f
= *decDoubleToWider (&temp
, &to
.f
);
396 #if defined (L_dd_to_td)
397 /* Use decNumber to convert directly from _Decimal64 to _Decimal128. */
399 DFP_TO_DFP (_Decimal64 f_from
)
401 union { _Decimal64 c
; decDouble f
; } from
;
402 union { _Decimal128 c
; decQuad f
; } to
;
405 to
.f
= *decDoubleToWider (&from
.f
, &to
.f
);
410 #if defined (L_dd_to_sd)
411 /* Use decNumber to convert directly from _Decimal64 to _Decimal32. */
413 DFP_TO_DFP (_Decimal64 f_from
)
415 union { _Decimal32 c
; decSingle f
; } to
;
416 union { _Decimal64 c
; decDouble f
; } from
;
419 decContextDefault (&context
, CONTEXT_INIT
);
420 DFP_INIT_ROUNDMODE (context
.round
);
422 to
.f
= *decSingleFromWider (&to
.f
, &from
.f
, &context
);
423 if (DFP_EXCEPTIONS_ENABLED
&& context
.status
!= 0)
424 dfp_conversion_exceptions (context
.status
);
429 #if defined (L_td_to_sd)
430 /* Use decNumber to convert directly from _Decimal128 to _Decimal32. */
432 DFP_TO_DFP (_Decimal128 f_from
)
434 union { _Decimal32 c
; decSingle f
; } to
;
435 union { _Decimal128 c
; decQuad f
; } from
;
439 decContextDefault (&context
, CONTEXT_INIT
);
440 DFP_INIT_ROUNDMODE (context
.round
);
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
);
450 #if defined (L_td_to_dd)
451 /* Use decNumber to convert directly from _Decimal128 to _Decimal64. */
453 DFP_TO_DFP (_Decimal128 f_from
)
455 union { _Decimal64 c
; decDouble f
; } to
;
456 union { _Decimal128 c
; decQuad f
; } from
;
459 decContextDefault (&context
, CONTEXT_INIT
);
460 DFP_INIT_ROUNDMODE (context
.round
);
462 to
.f
= *decDoubleFromWider (&to
.f
, &from
.f
, &context
);
463 if (DFP_EXCEPTIONS_ENABLED
&& context
.status
!= 0)
464 dfp_conversion_exceptions (context
.status
);
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. */
473 DFP_TO_INT (DFP_C_TYPE x
)
475 union { DFP_C_TYPE c
; decFloat f
; } u
;
479 decContextDefault (&context
, DEC_INIT_DECIMAL128
);
480 context
.round
= DEC_ROUND_DOWN
;
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
);
489 #if defined (L_sd_to_si) || (L_sd_to_usi)
490 /* Use decNumber to convert directly from decimal float to integer types. */
492 DFP_TO_INT (_Decimal32 x
)
494 union { _Decimal32 c
; decSingle f
; } u32
;
499 decContextDefault (&context
, DEC_INIT_DECIMAL128
);
500 context
.round
= DEC_ROUND_DOWN
;
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
);
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. */
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. */
526 decNumber qval
, n1
, n2
;
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
, '.');
548 /* Use a C library function to convert to the integral type. */
549 return STR_TO_INT (buf
, NULL
, 10);
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. */
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
);
566 #if defined (L_si_to_sd) || defined (L_usi_to_sd)
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
;
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
);
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. */
590 INT_TO_DFP (INT_TYPE i
)
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
);
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)
620 DFP_TO_BFP (DFP_C_TYPE f
)
625 HOST_TO_IEEE (f
, &s
);
626 /* Write the value to a string. */
628 /* Read it as the binary floating point type and return that. */
629 return STR_TO_BFP (buf
, NULL
);
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)
640 BFP_TO_DFP (BFP_TYPE x
)
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. */
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
);
666 DFP_HANDLE_EXCEPTIONS (ieee_flags
);
673 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
675 DFP_UNORD (DFP_C_TYPE arg_a
, DFP_C_TYPE arg_b
)
677 decNumber arg1
, arg2
;
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 */