xref: /dragonfly/contrib/mpfr/src/get_d64.c (revision ab6d115f)
14a238c70SJohn Marino /* mpfr_get_decimal64 -- convert a multiple precision floating-point number
24a238c70SJohn Marino                          to a IEEE 754r decimal64 float
34a238c70SJohn Marino 
44a238c70SJohn Marino See http://gcc.gnu.org/ml/gcc/2006-06/msg00691.html,
54a238c70SJohn Marino http://gcc.gnu.org/onlinedocs/gcc/Decimal-Float.html,
64a238c70SJohn Marino and TR 24732 <http://www.open-std.org/jtc1/sc22/wg14/www/projects#24732>.
74a238c70SJohn Marino 
8*ab6d115fSJohn Marino Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
9*ab6d115fSJohn Marino Contributed by the AriC and Caramel projects, INRIA.
104a238c70SJohn Marino 
114a238c70SJohn Marino This file is part of the GNU MPFR Library.
124a238c70SJohn Marino 
134a238c70SJohn Marino The GNU MPFR Library is free software; you can redistribute it and/or modify
144a238c70SJohn Marino it under the terms of the GNU Lesser General Public License as published by
154a238c70SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
164a238c70SJohn Marino option) any later version.
174a238c70SJohn Marino 
184a238c70SJohn Marino The GNU MPFR Library is distributed in the hope that it will be useful, but
194a238c70SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
204a238c70SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
214a238c70SJohn Marino License for more details.
224a238c70SJohn Marino 
234a238c70SJohn Marino You should have received a copy of the GNU Lesser General Public License
244a238c70SJohn Marino along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
254a238c70SJohn Marino http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
264a238c70SJohn Marino 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
274a238c70SJohn Marino 
284a238c70SJohn Marino #include <stdlib.h> /* for strtol */
294a238c70SJohn Marino #include "mpfr-impl.h"
304a238c70SJohn Marino 
314a238c70SJohn Marino #define ISDIGIT(c) ('0' <= c && c <= '9')
324a238c70SJohn Marino 
334a238c70SJohn Marino #ifdef MPFR_WANT_DECIMAL_FLOATS
344a238c70SJohn Marino 
35*ab6d115fSJohn Marino #ifndef DEC64_MAX
36*ab6d115fSJohn Marino # define DEC64_MAX 9.999999999999999E384dd
37*ab6d115fSJohn Marino #endif
38*ab6d115fSJohn Marino 
394a238c70SJohn Marino #ifdef DPD_FORMAT
404a238c70SJohn Marino static int T[1000] = {
414a238c70SJohn Marino   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 32,
424a238c70SJohn Marino   33, 34, 35, 36, 37, 38, 39, 40, 41, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
434a238c70SJohn Marino   64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 80, 81, 82, 83, 84, 85, 86, 87, 88,
444a238c70SJohn Marino   89, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, 115, 116,
454a238c70SJohn Marino   117, 118, 119, 120, 121, 10, 11, 42, 43, 74, 75, 106, 107, 78, 79, 26, 27,
464a238c70SJohn Marino   58, 59, 90, 91, 122, 123, 94, 95, 128, 129, 130, 131, 132, 133, 134, 135,
474a238c70SJohn Marino   136, 137, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 160, 161, 162,
484a238c70SJohn Marino   163, 164, 165, 166, 167, 168, 169, 176, 177, 178, 179, 180, 181, 182, 183,
494a238c70SJohn Marino   184, 185, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 208, 209, 210,
504a238c70SJohn Marino   211, 212, 213, 214, 215, 216, 217, 224, 225, 226, 227, 228, 229, 230, 231,
514a238c70SJohn Marino   232, 233, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 138, 139, 170,
524a238c70SJohn Marino   171, 202, 203, 234, 235, 206, 207, 154, 155, 186, 187, 218, 219, 250, 251,
534a238c70SJohn Marino   222, 223, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 272, 273, 274,
544a238c70SJohn Marino   275, 276, 277, 278, 279, 280, 281, 288, 289, 290, 291, 292, 293, 294, 295,
554a238c70SJohn Marino   296, 297, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 320, 321, 322,
564a238c70SJohn Marino   323, 324, 325, 326, 327, 328, 329, 336, 337, 338, 339, 340, 341, 342, 343,
574a238c70SJohn Marino   344, 345, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 368, 369, 370,
584a238c70SJohn Marino   371, 372, 373, 374, 375, 376, 377, 266, 267, 298, 299, 330, 331, 362, 363,
594a238c70SJohn Marino   334, 335, 282, 283, 314, 315, 346, 347, 378, 379, 350, 351, 384, 385, 386,
604a238c70SJohn Marino   387, 388, 389, 390, 391, 392, 393, 400, 401, 402, 403, 404, 405, 406, 407,
614a238c70SJohn Marino   408, 409, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 432, 433, 434,
624a238c70SJohn Marino   435, 436, 437, 438, 439, 440, 441, 448, 449, 450, 451, 452, 453, 454, 455,
634a238c70SJohn Marino   456, 457, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 480, 481, 482,
644a238c70SJohn Marino   483, 484, 485, 486, 487, 488, 489, 496, 497, 498, 499, 500, 501, 502, 503,
654a238c70SJohn Marino   504, 505, 394, 395, 426, 427, 458, 459, 490, 491, 462, 463, 410, 411, 442,
664a238c70SJohn Marino   443, 474, 475, 506, 507, 478, 479, 512, 513, 514, 515, 516, 517, 518, 519,
674a238c70SJohn Marino   520, 521, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 544, 545, 546,
684a238c70SJohn Marino   547, 548, 549, 550, 551, 552, 553, 560, 561, 562, 563, 564, 565, 566, 567,
694a238c70SJohn Marino   568, 569, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 592, 593, 594,
704a238c70SJohn Marino   595, 596, 597, 598, 599, 600, 601, 608, 609, 610, 611, 612, 613, 614, 615,
714a238c70SJohn Marino   616, 617, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 522, 523, 554,
724a238c70SJohn Marino   555, 586, 587, 618, 619, 590, 591, 538, 539, 570, 571, 602, 603, 634, 635,
734a238c70SJohn Marino   606, 607, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 656, 657, 658,
744a238c70SJohn Marino   659, 660, 661, 662, 663, 664, 665, 672, 673, 674, 675, 676, 677, 678, 679,
754a238c70SJohn Marino   680, 681, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 704, 705, 706,
764a238c70SJohn Marino   707, 708, 709, 710, 711, 712, 713, 720, 721, 722, 723, 724, 725, 726, 727,
774a238c70SJohn Marino   728, 729, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 752, 753, 754,
784a238c70SJohn Marino   755, 756, 757, 758, 759, 760, 761, 650, 651, 682, 683, 714, 715, 746, 747,
794a238c70SJohn Marino   718, 719, 666, 667, 698, 699, 730, 731, 762, 763, 734, 735, 768, 769, 770,
804a238c70SJohn Marino   771, 772, 773, 774, 775, 776, 777, 784, 785, 786, 787, 788, 789, 790, 791,
814a238c70SJohn Marino   792, 793, 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 816, 817, 818,
824a238c70SJohn Marino   819, 820, 821, 822, 823, 824, 825, 832, 833, 834, 835, 836, 837, 838, 839,
834a238c70SJohn Marino   840, 841, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 864, 865, 866,
844a238c70SJohn Marino   867, 868, 869, 870, 871, 872, 873, 880, 881, 882, 883, 884, 885, 886, 887,
854a238c70SJohn Marino   888, 889, 778, 779, 810, 811, 842, 843, 874, 875, 846, 847, 794, 795, 826,
864a238c70SJohn Marino   827, 858, 859, 890, 891, 862, 863, 896, 897, 898, 899, 900, 901, 902, 903,
874a238c70SJohn Marino   904, 905, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 928, 929, 930,
884a238c70SJohn Marino   931, 932, 933, 934, 935, 936, 937, 944, 945, 946, 947, 948, 949, 950, 951,
894a238c70SJohn Marino   952, 953, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 976, 977, 978,
904a238c70SJohn Marino   979, 980, 981, 982, 983, 984, 985, 992, 993, 994, 995, 996, 997, 998, 999,
914a238c70SJohn Marino   1000, 1001, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 906,
924a238c70SJohn Marino   907, 938, 939, 970, 971, 1002, 1003, 974, 975, 922, 923, 954, 955, 986,
934a238c70SJohn Marino   987, 1018, 1019, 990, 991, 12, 13, 268, 269, 524, 525, 780, 781, 46, 47, 28,
944a238c70SJohn Marino   29, 284, 285, 540, 541, 796, 797, 62, 63, 44, 45, 300, 301, 556, 557, 812,
954a238c70SJohn Marino   813, 302, 303, 60, 61, 316, 317, 572, 573, 828, 829, 318, 319, 76, 77,
964a238c70SJohn Marino   332, 333, 588, 589, 844, 845, 558, 559, 92, 93, 348, 349, 604, 605, 860,
974a238c70SJohn Marino   861, 574, 575, 108, 109, 364, 365, 620, 621, 876, 877, 814, 815, 124, 125,
984a238c70SJohn Marino   380, 381, 636, 637, 892, 893, 830, 831, 14, 15, 270, 271, 526, 527, 782,
994a238c70SJohn Marino   783, 110, 111, 30, 31, 286, 287, 542, 543, 798, 799, 126, 127, 140, 141,
1004a238c70SJohn Marino   396, 397, 652, 653, 908, 909, 174, 175, 156, 157, 412, 413, 668, 669, 924,
1014a238c70SJohn Marino   925, 190, 191, 172, 173, 428, 429, 684, 685, 940, 941, 430, 431, 188, 189,
1024a238c70SJohn Marino   444, 445, 700, 701, 956, 957, 446, 447, 204, 205, 460, 461, 716, 717, 972,
1034a238c70SJohn Marino   973, 686, 687, 220, 221, 476, 477, 732, 733, 988, 989, 702, 703, 236, 237,
1044a238c70SJohn Marino   492, 493, 748, 749, 1004, 1005, 942, 943, 252, 253, 508, 509, 764, 765,
1054a238c70SJohn Marino   1020, 1021, 958, 959, 142, 143, 398, 399, 654, 655, 910, 911, 238, 239, 158,
1064a238c70SJohn Marino   159, 414, 415, 670, 671, 926, 927, 254, 255};
1074a238c70SJohn Marino #endif
1084a238c70SJohn Marino 
1094a238c70SJohn Marino /* construct a decimal64 NaN */
1104a238c70SJohn Marino static _Decimal64
get_decimal64_nan(void)1114a238c70SJohn Marino get_decimal64_nan (void)
1124a238c70SJohn Marino {
1134a238c70SJohn Marino   union ieee_double_extract x;
1144a238c70SJohn Marino   union ieee_double_decimal64 y;
1154a238c70SJohn Marino 
1164a238c70SJohn Marino   x.s.exp = 1984; /* G[0]..G[4] = 11111: quiet NaN */
1174a238c70SJohn Marino   y.d = x.d;
1184a238c70SJohn Marino   return y.d64;
1194a238c70SJohn Marino }
1204a238c70SJohn Marino 
1214a238c70SJohn Marino /* construct the decimal64 Inf with given sign */
1224a238c70SJohn Marino static _Decimal64
get_decimal64_inf(int negative)1234a238c70SJohn Marino get_decimal64_inf (int negative)
1244a238c70SJohn Marino {
1254a238c70SJohn Marino   union ieee_double_extract x;
1264a238c70SJohn Marino   union ieee_double_decimal64 y;
1274a238c70SJohn Marino 
1284a238c70SJohn Marino   x.s.sig = (negative) ? 1 : 0;
1294a238c70SJohn Marino   x.s.exp = 1920; /* G[0]..G[4] = 11110: Inf */
1304a238c70SJohn Marino   y.d = x.d;
1314a238c70SJohn Marino   return y.d64;
1324a238c70SJohn Marino }
1334a238c70SJohn Marino 
1344a238c70SJohn Marino /* construct the decimal64 zero with given sign */
1354a238c70SJohn Marino static _Decimal64
get_decimal64_zero(int negative)1364a238c70SJohn Marino get_decimal64_zero (int negative)
1374a238c70SJohn Marino {
1384a238c70SJohn Marino   union ieee_double_decimal64 y;
1394a238c70SJohn Marino 
1404a238c70SJohn Marino   /* zero has the same representation in binary64 and decimal64 */
1414a238c70SJohn Marino   y.d = negative ? DBL_NEG_ZERO : 0.0;
1424a238c70SJohn Marino   return y.d64;
1434a238c70SJohn Marino }
1444a238c70SJohn Marino 
1454a238c70SJohn Marino /* construct the decimal64 smallest non-zero with given sign */
1464a238c70SJohn Marino static _Decimal64
get_decimal64_min(int negative)1474a238c70SJohn Marino get_decimal64_min (int negative)
1484a238c70SJohn Marino {
149*ab6d115fSJohn Marino   return negative ? - 1E-398dd : 1E-398dd;
1504a238c70SJohn Marino }
1514a238c70SJohn Marino 
1524a238c70SJohn Marino /* construct the decimal64 largest finite number with given sign */
1534a238c70SJohn Marino static _Decimal64
get_decimal64_max(int negative)1544a238c70SJohn Marino get_decimal64_max (int negative)
1554a238c70SJohn Marino {
156*ab6d115fSJohn Marino   return negative ? - DEC64_MAX : DEC64_MAX;
1574a238c70SJohn Marino }
1584a238c70SJohn Marino 
1594a238c70SJohn Marino /* one-to-one conversion:
1604a238c70SJohn Marino    s is a decimal string representing a number x = m * 10^e which must be
1614a238c70SJohn Marino    exactly representable in the decimal64 format, i.e.
1624a238c70SJohn Marino    (a) the mantissa m has at most 16 decimal digits
1634a238c70SJohn Marino    (b1) -383 <= e <= 384 with m integer multiple of 10^(-15), |m| < 10
1644a238c70SJohn Marino    (b2) or -398 <= e <= 369 with m integer, |m| < 10^16.
1654a238c70SJohn Marino    Assumes s is neither NaN nor +Inf nor -Inf.
1664a238c70SJohn Marino */
1674a238c70SJohn Marino static _Decimal64
string_to_Decimal64(char * s)1684a238c70SJohn Marino string_to_Decimal64 (char *s)
1694a238c70SJohn Marino {
1704a238c70SJohn Marino   long int exp = 0;
1714a238c70SJohn Marino   char m[17];
1724a238c70SJohn Marino   long n = 0; /* mantissa length */
1734a238c70SJohn Marino   char *endptr[1];
1744a238c70SJohn Marino   union ieee_double_extract x;
1754a238c70SJohn Marino   union ieee_double_decimal64 y;
1764a238c70SJohn Marino #ifdef DPD_FORMAT
1774a238c70SJohn Marino   unsigned int G, d1, d2, d3, d4, d5;
1784a238c70SJohn Marino #endif
1794a238c70SJohn Marino 
1804a238c70SJohn Marino   /* read sign */
1814a238c70SJohn Marino   if (*s == '-')
1824a238c70SJohn Marino     {
1834a238c70SJohn Marino       x.s.sig = 1;
1844a238c70SJohn Marino       s ++;
1854a238c70SJohn Marino     }
1864a238c70SJohn Marino   else
1874a238c70SJohn Marino     x.s.sig = 0;
1884a238c70SJohn Marino   /* read mantissa */
1894a238c70SJohn Marino   while (ISDIGIT (*s))
1904a238c70SJohn Marino     m[n++] = *s++;
1914a238c70SJohn Marino   exp = n;
1924a238c70SJohn Marino   if (*s == '.')
1934a238c70SJohn Marino     {
1944a238c70SJohn Marino       s ++;
1954a238c70SJohn Marino       while (ISDIGIT (*s))
1964a238c70SJohn Marino         m[n++] = *s++;
1974a238c70SJohn Marino     }
1984a238c70SJohn Marino   /* we have exp digits before decimal point, and a total of n digits */
1994a238c70SJohn Marino   exp -= n; /* we will consider an integer mantissa */
2004a238c70SJohn Marino   MPFR_ASSERTN(n <= 16);
2014a238c70SJohn Marino   if (*s == 'E' || *s == 'e')
2024a238c70SJohn Marino     exp += strtol (s + 1, endptr, 10);
2034a238c70SJohn Marino   else
2044a238c70SJohn Marino     *endptr = s;
2054a238c70SJohn Marino   MPFR_ASSERTN(**endptr == '\0');
2064a238c70SJohn Marino   MPFR_ASSERTN(-398 <= exp && exp <= (long) (385 - n));
2074a238c70SJohn Marino   while (n < 16)
2084a238c70SJohn Marino     {
2094a238c70SJohn Marino       m[n++] = '0';
2104a238c70SJohn Marino       exp --;
2114a238c70SJohn Marino     }
2124a238c70SJohn Marino   /* now n=16 and -398 <= exp <= 369 */
2134a238c70SJohn Marino   m[n] = '\0';
2144a238c70SJohn Marino 
2154a238c70SJohn Marino   /* compute biased exponent */
2164a238c70SJohn Marino   exp += 398;
2174a238c70SJohn Marino 
2184a238c70SJohn Marino   MPFR_ASSERTN(exp >= -15);
2194a238c70SJohn Marino   if (exp < 0)
2204a238c70SJohn Marino     {
2214a238c70SJohn Marino       int i;
2224a238c70SJohn Marino       n = -exp;
2234a238c70SJohn Marino       /* check the last n digits of the mantissa are zero */
2244a238c70SJohn Marino       for (i = 1; i <= n; i++)
2254a238c70SJohn Marino         MPFR_ASSERTN(m[16 - n] == '0');
2264a238c70SJohn Marino       /* shift the first (16-n) digits to the right */
2274a238c70SJohn Marino       for (i = 16 - n - 1; i >= 0; i--)
2284a238c70SJohn Marino         m[i + n] = m[i];
2294a238c70SJohn Marino       /* zero the first n digits */
2304a238c70SJohn Marino       for (i = 0; i < n; i ++)
2314a238c70SJohn Marino         m[i] = '0';
2324a238c70SJohn Marino       exp = 0;
2334a238c70SJohn Marino     }
2344a238c70SJohn Marino 
2354a238c70SJohn Marino   /* now convert to DPD or BID */
2364a238c70SJohn Marino #ifdef DPD_FORMAT
2374a238c70SJohn Marino #define CH(d) (d - '0')
2384a238c70SJohn Marino   if (m[0] >= '8')
2394a238c70SJohn Marino     G = (3 << 11) | ((exp & 768) << 1) | ((CH(m[0]) & 1) << 8);
2404a238c70SJohn Marino   else
2414a238c70SJohn Marino     G = ((exp & 768) << 3) | (CH(m[0]) << 8);
2424a238c70SJohn Marino   /* now the most 5 significant bits of G are filled */
2434a238c70SJohn Marino   G |= exp & 255;
2444a238c70SJohn Marino   d1 = T[100 * CH(m[1]) + 10 * CH(m[2]) + CH(m[3])]; /* 10-bit encoding */
2454a238c70SJohn Marino   d2 = T[100 * CH(m[4]) + 10 * CH(m[5]) + CH(m[6])]; /* 10-bit encoding */
2464a238c70SJohn Marino   d3 = T[100 * CH(m[7]) + 10 * CH(m[8]) + CH(m[9])]; /* 10-bit encoding */
2474a238c70SJohn Marino   d4 = T[100 * CH(m[10]) + 10 * CH(m[11]) + CH(m[12])]; /* 10-bit encoding */
2484a238c70SJohn Marino   d5 = T[100 * CH(m[13]) + 10 * CH(m[14]) + CH(m[15])]; /* 10-bit encoding */
2494a238c70SJohn Marino   x.s.exp = G >> 2;
2504a238c70SJohn Marino   x.s.manh = ((G & 3) << 18) | (d1 << 8) | (d2 >> 2);
2514a238c70SJohn Marino   x.s.manl = (d2 & 3) << 30;
2524a238c70SJohn Marino   x.s.manl |= (d3 << 20) | (d4 << 10) | d5;
2534a238c70SJohn Marino #else /* BID format */
2544a238c70SJohn Marino   {
2554a238c70SJohn Marino     mp_size_t rn;
2564a238c70SJohn Marino     mp_limb_t rp[2];
2574a238c70SJohn Marino     int case_i = strcmp (m, "9007199254740992") < 0;
2584a238c70SJohn Marino 
2594a238c70SJohn Marino     for (n = 0; n < 16; n++)
2604a238c70SJohn Marino       m[n] -= '0';
2614a238c70SJohn Marino     rn = mpn_set_str (rp, (unsigned char *) m, 16, 10);
2624a238c70SJohn Marino     if (rn == 1)
2634a238c70SJohn Marino       rp[1] = 0;
2644a238c70SJohn Marino #if GMP_NUMB_BITS > 32
2654a238c70SJohn Marino     rp[1] = rp[1] << (GMP_NUMB_BITS - 32);
2664a238c70SJohn Marino     rp[1] |= rp[0] >> 32;
2674a238c70SJohn Marino     rp[0] &= 4294967295UL;
2684a238c70SJohn Marino #endif
2694a238c70SJohn Marino     if (case_i)
2704a238c70SJohn Marino       {  /* s < 2^53: case i) */
2714a238c70SJohn Marino         x.s.exp = exp << 1;
2724a238c70SJohn Marino         x.s.manl = rp[0];           /* 32 bits */
2734a238c70SJohn Marino         x.s.manh = rp[1] & 1048575; /* 20 low bits */
2744a238c70SJohn Marino         x.s.exp |= rp[1] >> 20;     /* 1 bit */
2754a238c70SJohn Marino       }
2764a238c70SJohn Marino     else /* s >= 2^53: case ii) */
2774a238c70SJohn Marino       {
2784a238c70SJohn Marino         x.s.exp = 1536 | (exp >> 1);
2794a238c70SJohn Marino         x.s.manl = rp[0];
2804a238c70SJohn Marino         x.s.manh = (rp[1] ^ 2097152) | ((exp & 1) << 19);
2814a238c70SJohn Marino       }
2824a238c70SJohn Marino   }
2834a238c70SJohn Marino #endif /* DPD_FORMAT */
2844a238c70SJohn Marino   y.d = x.d;
2854a238c70SJohn Marino   return y.d64;
2864a238c70SJohn Marino }
2874a238c70SJohn Marino 
2884a238c70SJohn Marino _Decimal64
mpfr_get_decimal64(mpfr_srcptr src,mpfr_rnd_t rnd_mode)2894a238c70SJohn Marino mpfr_get_decimal64 (mpfr_srcptr src, mpfr_rnd_t rnd_mode)
2904a238c70SJohn Marino {
2914a238c70SJohn Marino   int negative;
2924a238c70SJohn Marino   mpfr_exp_t e;
2934a238c70SJohn Marino 
2944a238c70SJohn Marino   /* the encoding of NaN, Inf, zero is the same under DPD or BID */
2954a238c70SJohn Marino   if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (src)))
2964a238c70SJohn Marino     {
2974a238c70SJohn Marino       if (MPFR_IS_NAN (src))
2984a238c70SJohn Marino         return get_decimal64_nan ();
2994a238c70SJohn Marino 
3004a238c70SJohn Marino       negative = MPFR_IS_NEG (src);
3014a238c70SJohn Marino 
3024a238c70SJohn Marino       if (MPFR_IS_INF (src))
3034a238c70SJohn Marino         return get_decimal64_inf (negative);
3044a238c70SJohn Marino 
3054a238c70SJohn Marino       MPFR_ASSERTD (MPFR_IS_ZERO(src));
3064a238c70SJohn Marino       return get_decimal64_zero (negative);
3074a238c70SJohn Marino     }
3084a238c70SJohn Marino 
3094a238c70SJohn Marino   e = MPFR_GET_EXP (src);
3104a238c70SJohn Marino   negative = MPFR_IS_NEG (src);
3114a238c70SJohn Marino 
3124a238c70SJohn Marino   if (MPFR_UNLIKELY(rnd_mode == MPFR_RNDA))
3134a238c70SJohn Marino     rnd_mode = negative ? MPFR_RNDD : MPFR_RNDU;
3144a238c70SJohn Marino 
3154a238c70SJohn Marino   /* the smallest decimal64 number is 10^(-398),
3164a238c70SJohn Marino      with 2^(-1323) < 10^(-398) < 2^(-1322) */
3174a238c70SJohn Marino   if (MPFR_UNLIKELY (e < -1323)) /* src <= 2^(-1324) < 1/2*10^(-398) */
3184a238c70SJohn Marino     {
3194a238c70SJohn Marino       if (rnd_mode == MPFR_RNDZ || rnd_mode == MPFR_RNDN
3204a238c70SJohn Marino           || (rnd_mode == MPFR_RNDD && negative == 0)
3214a238c70SJohn Marino           || (rnd_mode == MPFR_RNDU && negative != 0))
3224a238c70SJohn Marino         return get_decimal64_zero (negative);
3234a238c70SJohn Marino       else /* return the smallest non-zero number */
3244a238c70SJohn Marino         return get_decimal64_min (negative);
3254a238c70SJohn Marino     }
3264a238c70SJohn Marino   /* the largest decimal64 number is just below 10^(385) < 2^1279 */
3274a238c70SJohn Marino   else if (MPFR_UNLIKELY (e > 1279)) /* then src >= 2^1279 */
3284a238c70SJohn Marino     {
329*ab6d115fSJohn Marino       if (rnd_mode == MPFR_RNDZ
330*ab6d115fSJohn Marino           || (rnd_mode == MPFR_RNDU && negative != 0)
3314a238c70SJohn Marino           || (rnd_mode == MPFR_RNDD && negative == 0))
3324a238c70SJohn Marino         return get_decimal64_max (negative);
3334a238c70SJohn Marino       else
3344a238c70SJohn Marino         return get_decimal64_inf (negative);
3354a238c70SJohn Marino     }
3364a238c70SJohn Marino   else
3374a238c70SJohn Marino     {
3384a238c70SJohn Marino       /* we need to store the sign (1), the mantissa (16), and the terminating
3394a238c70SJohn Marino          character, thus we need at least 18 characters in s */
3404a238c70SJohn Marino       char s[23];
3414a238c70SJohn Marino       mpfr_get_str (s, &e, 10, 16, src, rnd_mode);
3424a238c70SJohn Marino       /* the smallest normal number is 1.000...000E-383,
3434a238c70SJohn Marino          which corresponds to s=[0.]1000...000 and e=-382 */
3444a238c70SJohn Marino       if (e < -382)
3454a238c70SJohn Marino         {
3464a238c70SJohn Marino           /* the smallest subnormal number is 0.000...001E-383 = 1E-398,
3474a238c70SJohn Marino              which corresponds to s=[0.]1000...000 and e=-397 */
3484a238c70SJohn Marino           if (e < -397)
3494a238c70SJohn Marino             {
350*ab6d115fSJohn Marino               if (rnd_mode == MPFR_RNDN && e == -398)
351*ab6d115fSJohn Marino                 {
352*ab6d115fSJohn Marino                   /* If 0.5E-398 < |src| < 1E-398 (smallest subnormal),
353*ab6d115fSJohn Marino                      src should round to +/- 1E-398 in MPFR_RNDN. */
354*ab6d115fSJohn Marino                   mpfr_get_str (s, &e, 10, 1, src, MPFR_RNDA);
355*ab6d115fSJohn Marino                   return e == -398 && s[negative] <= '5' ?
356*ab6d115fSJohn Marino                     get_decimal64_zero (negative) :
357*ab6d115fSJohn Marino                     get_decimal64_min (negative);
358*ab6d115fSJohn Marino                 }
3594a238c70SJohn Marino               if (rnd_mode == MPFR_RNDZ || rnd_mode == MPFR_RNDN
3604a238c70SJohn Marino                   || (rnd_mode == MPFR_RNDD && negative == 0)
3614a238c70SJohn Marino                   || (rnd_mode == MPFR_RNDU && negative != 0))
3624a238c70SJohn Marino                 return get_decimal64_zero (negative);
3634a238c70SJohn Marino               else /* return the smallest non-zero number */
3644a238c70SJohn Marino                 return get_decimal64_min (negative);
3654a238c70SJohn Marino             }
3664a238c70SJohn Marino           else
3674a238c70SJohn Marino             {
3684a238c70SJohn Marino               mpfr_exp_t e2;
3694a238c70SJohn Marino               long digits = 16 - (-382 - e);
3704a238c70SJohn Marino               /* if e = -397 then 16 - (-382 - e) = 1 */
3714a238c70SJohn Marino               mpfr_get_str (s, &e2, 10, digits, src, rnd_mode);
3724a238c70SJohn Marino               /* Warning: we can have e2 = e + 1 here, when rounding to
3734a238c70SJohn Marino                  nearest or away from zero. */
3744a238c70SJohn Marino               s[negative + digits] = 'E';
3754a238c70SJohn Marino               sprintf (s + negative + digits + 1, "%ld",
3764a238c70SJohn Marino                        (long int)e2 - digits);
3774a238c70SJohn Marino               return string_to_Decimal64 (s);
3784a238c70SJohn Marino             }
3794a238c70SJohn Marino         }
3804a238c70SJohn Marino       /* the largest number is 9.999...999E+384,
3814a238c70SJohn Marino          which corresponds to s=[0.]9999...999 and e=385 */
3824a238c70SJohn Marino       else if (e > 385)
3834a238c70SJohn Marino         {
384*ab6d115fSJohn Marino           if (rnd_mode == MPFR_RNDZ
385*ab6d115fSJohn Marino               || (rnd_mode == MPFR_RNDU && negative != 0)
3864a238c70SJohn Marino               || (rnd_mode == MPFR_RNDD && negative == 0))
3874a238c70SJohn Marino             return get_decimal64_max (negative);
3884a238c70SJohn Marino           else
3894a238c70SJohn Marino             return get_decimal64_inf (negative);
3904a238c70SJohn Marino         }
3914a238c70SJohn Marino       else /* -382 <= e <= 385 */
3924a238c70SJohn Marino         {
3934a238c70SJohn Marino           s[16 + negative] = 'E';
3944a238c70SJohn Marino           sprintf (s + 17 + negative, "%ld", (long int)e - 16);
3954a238c70SJohn Marino           return string_to_Decimal64 (s);
3964a238c70SJohn Marino         }
3974a238c70SJohn Marino     }
3984a238c70SJohn Marino }
3994a238c70SJohn Marino 
4004a238c70SJohn Marino #endif /* MPFR_WANT_DECIMAL_FLOATS */
401