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