comparison gcc/config/dfp-bit.c @ 0:a06113de4d67

first commit
author kent <kent@cr.ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 14:47:48 +0900
parents
children 855418dad1a3
comparison
equal deleted inserted replaced
-1:000000000000 0:a06113de4d67
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
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
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 context.round = DEC_ROUND_DOWN;
572 f64 = *DEC_FLOAT_FROM_INT (&f64, i);
573 u32.f = *decSingleFromWider (&u32.f, &f64, &context);
574 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
575 dfp_conversion_exceptions (context.status);
576 return u32.c;
577 }
578 #endif
579
580 #if defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
581 || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
582 /* decNumber doesn't provide support for conversions from 64-bit integer
583 types, so do it the hard way. */
584 DFP_C_TYPE
585 INT_TO_DFP (INT_TYPE i)
586 {
587 DFP_C_TYPE f;
588 IEEE_TYPE s;
589 char buf[BUFMAX];
590 decContext context;
591
592 decContextDefault (&context, CONTEXT_INIT);
593 DFP_INIT_ROUNDMODE (context.round);
594
595 /* Use a C library function to get a floating point string. */
596 sprintf (buf, INT_FMT ".0", CAST_FOR_FMT(i));
597 /* Convert from the floating point string to a decimal* type. */
598 FROM_STRING (&s, buf, &context);
599 IEEE_TO_HOST (s, &f);
600
601 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
602 dfp_conversion_exceptions (context.status);
603
604 return f;
605 }
606 #endif
607
608 #if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
609 || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
610 || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
611 && LONG_DOUBLE_HAS_XF_MODE) \
612 || ((defined (L_sd_to_tf) || defined (L_dd_to_tf) || defined (L_td_to_tf)) \
613 && LONG_DOUBLE_HAS_TF_MODE)
614 BFP_TYPE
615 DFP_TO_BFP (DFP_C_TYPE f)
616 {
617 IEEE_TYPE s;
618 char buf[BUFMAX];
619
620 HOST_TO_IEEE (f, &s);
621 /* Write the value to a string. */
622 TO_STRING (&s, buf);
623 /* Read it as the binary floating point type and return that. */
624 return STR_TO_BFP (buf, NULL);
625 }
626 #endif
627
628 #if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
629 || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
630 || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
631 && LONG_DOUBLE_HAS_XF_MODE) \
632 || ((defined (L_tf_to_sd) || defined (L_tf_to_dd) || defined (L_tf_to_td)) \
633 && LONG_DOUBLE_HAS_TF_MODE)
634 DFP_C_TYPE
635 BFP_TO_DFP (BFP_TYPE x)
636 {
637 DFP_C_TYPE f;
638 IEEE_TYPE s;
639 char buf[BUFMAX];
640 decContext context;
641
642 decContextDefault (&context, CONTEXT_INIT);
643 DFP_INIT_ROUNDMODE (context.round);
644
645 /* Use a C library function to write the floating point value to a string. */
646 sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
647
648 /* Convert from the floating point string to a decimal* type. */
649 FROM_STRING (&s, buf, &context);
650 IEEE_TO_HOST (s, &f);
651
652 if (DFP_EXCEPTIONS_ENABLED && context.status != 0)
653 {
654 /* decNumber exception flags we care about here. */
655 int ieee_flags;
656 int dec_flags = DEC_IEEE_854_Inexact | DEC_IEEE_854_Invalid_operation
657 | DEC_IEEE_854_Overflow | DEC_IEEE_854_Underflow;
658 dec_flags &= context.status;
659 ieee_flags = DFP_IEEE_FLAGS (dec_flags);
660 if (ieee_flags != 0)
661 DFP_HANDLE_EXCEPTIONS (ieee_flags);
662 }
663
664 return f;
665 }
666 #endif
667
668 #if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
669 CMPtype
670 DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
671 {
672 decNumber arg1, arg2;
673 IEEE_TYPE a, b;
674
675 HOST_TO_IEEE (arg_a, &a);
676 HOST_TO_IEEE (arg_b, &b);
677 TO_INTERNAL (&a, &arg1);
678 TO_INTERNAL (&b, &arg2);
679 return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
680 }
681 #endif /* L_unord_sd || L_unord_dd || L_unord_td */