OSDN Git Service

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