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