1 /* This is a software decimal floating point library. 2 Copyright (C) 2005-2019 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 "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 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 */ 681