File indexing completed on 2025-09-15 08:30:31
0001
0002
0003
0004
0005
0006 #ifndef BOOST_CHARCONV_DETAIL_RYU_RYU_GENERIC_128_HPP
0007 #define BOOST_CHARCONV_DETAIL_RYU_RYU_GENERIC_128_HPP
0008
0009 #include <boost/charconv/detail/ryu/generic_128.hpp>
0010 #include <boost/charconv/detail/integer_search_trees.hpp>
0011 #include <boost/charconv/detail/config.hpp>
0012 #include <boost/charconv/detail/bit_layouts.hpp>
0013 #include <boost/charconv/to_chars.hpp>
0014 #include <cinttypes>
0015 #include <cstdio>
0016 #include <cstdint>
0017
0018 #ifdef BOOST_CHARCONV_DEBUG
0019 # include <iostream>
0020 #endif
0021
0022 namespace boost { namespace charconv { namespace detail { namespace ryu {
0023
0024 static constexpr int32_t fd128_exceptional_exponent = 0x7FFFFFFF;
0025 static constexpr unsigned_128_type one = 1;
0026
0027 struct floating_decimal_128
0028 {
0029 unsigned_128_type mantissa;
0030 int32_t exponent;
0031 bool sign;
0032 };
0033
0034 #ifdef BOOST_CHARCONV_DEBUG
0035 static char* s(unsigned_128_type v) {
0036 int len = num_digits(v);
0037 char* b = static_cast<char*>(malloc((len + 1) * sizeof(char)));
0038 for (int i = 0; i < len; i++) {
0039 const uint32_t c = static_cast<uint32_t>(v % 10);
0040 v /= 10;
0041 b[len - 1 - i] = static_cast<char>('0' + c);
0042 }
0043 b[len] = 0;
0044 return b;
0045 }
0046 #endif
0047
0048 static inline struct floating_decimal_128 generic_binary_to_decimal(
0049 const unsigned_128_type bits,
0050 const uint32_t mantissaBits, const uint32_t exponentBits, const bool explicitLeadingBit) noexcept
0051 {
0052 #ifdef BOOST_CHARCONV_DEBUG
0053 printf("IN=");
0054 for (int32_t bit = 127; bit >= 0; --bit)
0055 {
0056 printf("%u", static_cast<uint32_t>((bits >> bit) & 1));
0057 }
0058 printf("\n");
0059 #endif
0060
0061 const uint32_t bias = (1u << (exponentBits - 1)) - 1;
0062 const bool ieeeSign = ((bits >> (mantissaBits + exponentBits)) & 1) != 0;
0063 const unsigned_128_type ieeeMantissa = bits & ((one << mantissaBits) - 1);
0064 const uint32_t ieeeExponent = static_cast<uint32_t>((bits >> mantissaBits) & ((one << exponentBits) - 1u));
0065
0066 if (ieeeExponent == 0 && ieeeMantissa == 0)
0067 {
0068 struct floating_decimal_128 fd {0, 0, ieeeSign};
0069 return fd;
0070 }
0071 if (ieeeExponent == ((1u << exponentBits) - 1u))
0072 {
0073 struct floating_decimal_128 fd;
0074 fd.mantissa = explicitLeadingBit ? ieeeMantissa & ((one << (mantissaBits - 1)) - 1) : ieeeMantissa;
0075 fd.exponent = fd128_exceptional_exponent;
0076 fd.sign = ieeeSign;
0077 return fd;
0078 }
0079
0080 int32_t e2;
0081 unsigned_128_type m2;
0082
0083 if (explicitLeadingBit)
0084 {
0085
0086 if (ieeeExponent == 0)
0087 {
0088 e2 = static_cast<int32_t>(1 - bias - mantissaBits + 1 - 2);
0089 }
0090 else
0091 {
0092 e2 = static_cast<int32_t>(ieeeExponent - bias - mantissaBits + 1 - 2);
0093 }
0094 m2 = ieeeMantissa;
0095 }
0096 else
0097 {
0098 if (ieeeExponent == 0)
0099 {
0100 e2 = static_cast<int32_t>(1 - bias - mantissaBits - 2);
0101 m2 = ieeeMantissa;
0102 } else
0103 {
0104 e2 = static_cast<int32_t>(ieeeExponent - bias - mantissaBits - 2U);
0105 m2 = (one << mantissaBits) | ieeeMantissa;
0106 }
0107 }
0108 const bool even = (m2 & 1) == 0;
0109 const bool acceptBounds = even;
0110
0111 #ifdef BOOST_CHARCONV_DEBUG
0112 printf("-> %s %s * 2^%d\n", ieeeSign ? "-" : "+", s(m2), e2 + 2);
0113 #endif
0114
0115
0116 const unsigned_128_type mv = 4 * m2;
0117
0118 const uint32_t mmShift =
0119 (ieeeMantissa != (explicitLeadingBit ? one << (mantissaBits - 1) : 0))
0120 || (ieeeExponent == 0);
0121
0122
0123 unsigned_128_type vr;
0124 unsigned_128_type vp;
0125 unsigned_128_type vm;
0126 int32_t e10;
0127 bool vmIsTrailingZeros = false;
0128 bool vrIsTrailingZeros = false;
0129 if (e2 >= 0)
0130 {
0131
0132
0133 const uint32_t q = log10Pow2(e2) - (e2 > 3);
0134 e10 = static_cast<int32_t>(q);
0135 const int32_t k = BOOST_CHARCONV_POW5_INV_BITCOUNT + static_cast<int32_t>(pow5bits(q)) - 1;
0136 const int32_t i = -e2 + static_cast<int32_t>(q) + k;
0137 uint64_t pow5[4];
0138 generic_computeInvPow5(q, pow5);
0139 vr = mulShift(4 * m2, pow5, i);
0140 vp = mulShift(4 * m2 + 2, pow5, i);
0141 vm = mulShift(4 * m2 - 1 - mmShift, pow5, i);
0142
0143 #ifdef BOOST_CHARCONV_DEBUG
0144 printf("%s * 2^%d / 10^%d\n", s(mv), e2, q);
0145 printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
0146 #endif
0147
0148
0149 if (q <= 55)
0150 {
0151
0152 if (mv % 5 == 0)
0153 {
0154 vrIsTrailingZeros = multipleOfPowerOf5(mv, q - 1);
0155 }
0156 else if (acceptBounds)
0157 {
0158
0159
0160
0161 vmIsTrailingZeros = multipleOfPowerOf5(mv - 1 - mmShift, q);
0162 }
0163 else
0164 {
0165
0166 vp -= multipleOfPowerOf5(mv + 2, q);
0167 }
0168 }
0169 }
0170 else
0171 {
0172
0173 const uint32_t q = log10Pow5(-e2) - static_cast<uint32_t>(-e2 > 1);
0174 e10 = static_cast<int32_t>(q) + e2;
0175 const int32_t i = -e2 - static_cast<int32_t>(q);
0176 const int32_t k = static_cast<int32_t>(pow5bits(static_cast<uint32_t>(i))) - BOOST_CHARCONV_POW5_BITCOUNT;
0177 const int32_t j = static_cast<int32_t>(q) - k;
0178 uint64_t pow5[4];
0179 generic_computePow5(static_cast<uint32_t>(i), pow5);
0180 vr = mulShift(4 * m2, pow5, j);
0181 vp = mulShift(4 * m2 + 2, pow5, j);
0182 vm = mulShift(4 * m2 - 1 - mmShift, pow5, j);
0183
0184 #ifdef BOOST_CHARCONV_DEBUG
0185 printf("%s * 5^%d / 10^%d\n", s(mv), -e2, q);
0186 printf("%d %d %d %d\n", q, i, k, j);
0187 printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
0188 #endif
0189
0190 if (q <= 1)
0191 {
0192
0193
0194 vrIsTrailingZeros = true;
0195 if (acceptBounds)
0196 {
0197
0198 vmIsTrailingZeros = mmShift == 1;
0199 }
0200 else
0201 {
0202
0203 --vp;
0204 }
0205 }
0206 else if (q < 127)
0207 {
0208
0209
0210
0211
0212
0213 vrIsTrailingZeros = multipleOfPowerOf2(mv, q - 1);
0214
0215 #ifdef BOOST_CHARCONV_DEBUG
0216 printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
0217 #endif
0218 }
0219 }
0220
0221 #ifdef BOOST_CHARCONV_DEBUG
0222 printf("e10=%d\n", e10);
0223 printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
0224 printf("vm is trailing zeros=%s\n", vmIsTrailingZeros ? "true" : "false");
0225 printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
0226 #endif
0227
0228
0229 uint32_t removed = 0;
0230 uint8_t lastRemovedDigit = 0;
0231 unsigned_128_type output;
0232
0233 while (vp / 10 > vm / 10)
0234 {
0235 vmIsTrailingZeros &= vm % 10 == 0;
0236 vrIsTrailingZeros &= lastRemovedDigit == 0;
0237 lastRemovedDigit = static_cast<uint8_t>(vr % 10);
0238 vr /= 10;
0239 vp /= 10;
0240 vm /= 10;
0241 ++removed;
0242 }
0243
0244 #ifdef BOOST_CHARCONV_DEBUG
0245 printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
0246 printf("d-10=%s\n", vmIsTrailingZeros ? "true" : "false");
0247 #endif
0248
0249 if (vmIsTrailingZeros)
0250 {
0251 while (vm % 10 == 0)
0252 {
0253 vrIsTrailingZeros &= lastRemovedDigit == 0;
0254 lastRemovedDigit = static_cast<uint8_t>(vr % 10);
0255 vr /= 10;
0256 vp /= 10;
0257 vm /= 10;
0258 ++removed;
0259 }
0260 }
0261
0262 #ifdef BOOST_CHARCONV_DEBUG
0263 printf("%s %d\n", s(vr), lastRemovedDigit);
0264 printf("vr is trailing zeros=%s\n", vrIsTrailingZeros ? "true" : "false");
0265 #endif
0266
0267 if (vrIsTrailingZeros && (lastRemovedDigit == 5) && (vr % 2 == 0))
0268 {
0269
0270 lastRemovedDigit = 4;
0271 }
0272
0273 output = vr + static_cast<unsigned_128_type>((vr == vm && (!acceptBounds || !vmIsTrailingZeros)) || (lastRemovedDigit >= 5));
0274 const int32_t exp = e10 + static_cast<int32_t>(removed);
0275
0276 #ifdef BOOST_CHARCONV_DEBUG
0277 printf("V+=%s\nV =%s\nV-=%s\n", s(vp), s(vr), s(vm));
0278 printf("O=%s\n", s(output));
0279 printf("EXP=%d\n", exp);
0280 #endif
0281
0282 return {output, exp, ieeeSign};
0283 }
0284
0285 static inline int copy_special_str(char* result, const std::ptrdiff_t result_size, const struct floating_decimal_128 fd) noexcept
0286 {
0287 if (fd.sign)
0288 {
0289 *result = '-';
0290 ++result;
0291 }
0292
0293 if (fd.mantissa)
0294 {
0295 if (fd.sign)
0296 {
0297 if (fd.mantissa == static_cast<unsigned_128_type>(2305843009213693952) ||
0298 fd.mantissa == static_cast<unsigned_128_type>(6917529027641081856) ||
0299 fd.mantissa == static_cast<unsigned_128_type>(1) << 110)
0300 {
0301 if (result_size >= 10)
0302 {
0303 std::memcpy(result, "nan(snan)", 9);
0304 return 10;
0305 }
0306 else
0307 {
0308 return -1;
0309 }
0310 }
0311 else
0312 {
0313 if (result_size >= 9)
0314 {
0315 std::memcpy(result, "nan(ind)", 8);
0316 return 9;
0317 }
0318 else
0319 {
0320 return -1;
0321 }
0322 }
0323 }
0324 else
0325 {
0326 if (fd.mantissa == static_cast<unsigned_128_type>(2305843009213693952) ||
0327 fd.mantissa == static_cast<unsigned_128_type>(6917529027641081856) ||
0328 fd.mantissa == static_cast<unsigned_128_type>(1) << 110)
0329 {
0330 if (result_size >= 9)
0331 {
0332 std::memcpy(result, "nan(snan)", 9);
0333 return 9;
0334 }
0335 else
0336 {
0337 return -1;
0338 }
0339 }
0340 else
0341 {
0342 if (result_size >= 3)
0343 {
0344 std::memcpy(result, "nan", 3);
0345 return 3;
0346 }
0347 else
0348 {
0349 return -1;
0350 }
0351 }
0352 }
0353 }
0354
0355 if (result_size >= 3 + static_cast<std::ptrdiff_t>(fd.sign))
0356 {
0357 memcpy(result, "inf", 3);
0358 return static_cast<int>(fd.sign) + 3;
0359 }
0360
0361 return -1;
0362 }
0363
0364 static inline int generic_to_chars_fixed(const struct floating_decimal_128 v, char* result, const ptrdiff_t result_size, int precision) noexcept
0365 {
0366 if (v.exponent == fd128_exceptional_exponent)
0367 {
0368 return copy_special_str(result, result_size, v);
0369 }
0370
0371
0372 if (v.sign)
0373 {
0374 *result++ = '-';
0375 }
0376
0377 unsigned_128_type output = v.mantissa;
0378 const auto r = to_chars_128integer_impl(result, result + result_size, output);
0379 if (r.ec != std::errc())
0380 {
0381 return -static_cast<int>(r.ec);
0382 }
0383
0384 auto current_len = static_cast<int>(r.ptr - result);
0385
0386 #ifdef BOOST_CHARCONV_DEBUG
0387 char* man_print = s(v.mantissa);
0388 std::cerr << "Exp: " << v.exponent
0389 << "\nMantissa: " << man_print
0390 << "\nMan len: " << current_len << std::endl;
0391 free(man_print);
0392 #endif
0393
0394 if (v.exponent == 0)
0395 {
0396
0397 if (precision > 0)
0398 {
0399 result[current_len++] = '.';
0400 memset(result+current_len, '0', static_cast<size_t>(precision));
0401 current_len += precision;
0402 precision = 0;
0403 }
0404 }
0405 else if (v.exponent > 0)
0406 {
0407
0408
0409 if (current_len + v.exponent > result_size)
0410 {
0411 return -static_cast<int>(std::errc::value_too_large);
0412 }
0413
0414 result = r.ptr;
0415 memset(result, '0', static_cast<std::size_t>(v.exponent));
0416 result += static_cast<std::size_t>(v.exponent);
0417 *result++ = '.';
0418 current_len += v.exponent + 1;
0419 }
0420 else if ((-v.exponent) < current_len)
0421 {
0422
0423 if (current_len + v.exponent + 1 > result_size)
0424 {
0425 return -static_cast<int>(std::errc::result_out_of_range);
0426 }
0427
0428 memmove(result + current_len + v.exponent + 1, result + current_len + v.exponent, static_cast<std::size_t>(-v.exponent));
0429 const auto shift = result + current_len + v.exponent;
0430 const auto shift_width = (shift - result) + 1;
0431 memcpy(shift, ".", 1U);
0432 ++current_len;
0433 if (current_len - shift_width > precision)
0434 {
0435 if (precision > 0)
0436 {
0437 current_len = static_cast<int>(shift_width) + precision;
0438 }
0439
0440 precision = 0;
0441
0442
0443 const auto round_val = result[current_len];
0444 result[current_len] = '\0';
0445
0446
0447
0448 if (round_val >= '5')
0449 {
0450 auto current_spot = current_len - 1;
0451 bool continue_rounding = true;
0452 while (result[current_spot] != '.' && continue_rounding)
0453 {
0454 if (result[current_spot] < '9')
0455 {
0456 result[current_spot] = static_cast<char>(static_cast<int>(result[current_spot]) + 1);
0457 continue_rounding = false;
0458 }
0459 else
0460 {
0461 result[current_spot] = '0';
0462 continue_rounding = true;
0463 }
0464 --current_spot;
0465 }
0466 BOOST_CHARCONV_ASSERT(!continue_rounding);
0467 }
0468 }
0469 else
0470 {
0471 precision -= current_len - static_cast<int>(shift_width);
0472 result += current_len + v.exponent + 1;
0473 }
0474 }
0475 else
0476 {
0477
0478 if (-v.exponent + 2 > result_size)
0479 {
0480 return -static_cast<int>(std::errc::value_too_large);
0481 }
0482
0483 memmove(result - v.exponent - current_len + 2, result, static_cast<std::size_t>(current_len));
0484 memcpy(result, "0.", 2U);
0485 memset(result + 2, '0', static_cast<std::size_t>(0 - v.exponent - current_len));
0486 current_len = -v.exponent + 2;
0487 precision -= current_len - 2;
0488 result += current_len;
0489 }
0490
0491 if (precision > 0)
0492 {
0493 if (current_len + precision > result_size)
0494 {
0495 return -static_cast<int>(std::errc::result_out_of_range);
0496 }
0497
0498 memset(result, '0', static_cast<std::size_t>(precision));
0499 current_len += precision;
0500 }
0501
0502 return current_len + static_cast<int>(v.sign);
0503 }
0504
0505
0506
0507
0508
0509
0510
0511
0512 static inline int generic_to_chars(const struct floating_decimal_128 v, char* result, const ptrdiff_t result_size,
0513 chars_format fmt = chars_format::general, int precision = -1) noexcept
0514 {
0515 if (v.exponent == fd128_exceptional_exponent)
0516 {
0517 return copy_special_str(result, result_size, v);
0518 }
0519
0520 unsigned_128_type output = v.mantissa;
0521 const uint32_t olength = static_cast<uint32_t>(num_digits(output));
0522
0523 #ifdef BOOST_CHARCONV_DEBUG
0524 printf("DIGITS=%s\n", s(v.mantissa));
0525 printf("OLEN=%u\n", olength);
0526 printf("EXP=%u\n", v.exponent + olength);
0527 #endif
0528
0529
0530 if (fmt == chars_format::general)
0531 {
0532 const int64_t exp = v.exponent + static_cast<int64_t>(olength);
0533 if (std::abs(exp) <= olength)
0534 {
0535 auto ptr = generic_to_chars_fixed(v, result, result_size, precision);
0536 if (ptr >= 1 && result[ptr - 1] == '0')
0537 {
0538 --ptr;
0539 while (ptr > 0 && result[ptr] == '0')
0540 {
0541 --ptr;
0542 }
0543 ++ptr;
0544 }
0545 return ptr;
0546 }
0547 }
0548
0549
0550 size_t index = 0;
0551 if (v.sign)
0552 {
0553 result[index++] = '-';
0554 }
0555
0556 if (index + olength > static_cast<size_t>(result_size))
0557 {
0558 return -static_cast<int>(std::errc::value_too_large);
0559 }
0560 else if (olength == 0)
0561 {
0562 return -2;
0563 }
0564
0565 for (uint32_t i = 0; i < olength - 1; ++i)
0566 {
0567 const auto c = static_cast<uint32_t>(output % 10);
0568 output /= 10;
0569 result[index + olength - i] = static_cast<char>('0' + c);
0570 }
0571 BOOST_CHARCONV_ASSERT(output < 10);
0572 result[index] = static_cast<char>('0' + static_cast<uint32_t>(output % 10));
0573
0574
0575 if (olength > 1)
0576 {
0577 result[index + 1] = '.';
0578 index += olength + 1;
0579 }
0580 else
0581 {
0582 ++index;
0583 }
0584
0585
0586 if (precision != -1)
0587 {
0588 if (static_cast<size_t>(precision) < index)
0589 {
0590 if (fmt != chars_format::scientific)
0591 {
0592 index = static_cast<size_t>(precision) + 1 + static_cast<size_t>(v.sign);
0593 }
0594 else
0595 {
0596 index = static_cast<size_t>(precision) + 2 + static_cast<size_t>(v.sign);
0597 }
0598
0599
0600 if (result[index] >= '5' && index < olength + 1 + static_cast<size_t>(v.sign))
0601 {
0602 bool continue_rounding = false;
0603 auto current_index = index;
0604 do
0605 {
0606 --current_index;
0607 if (result[current_index] == '9')
0608 {
0609 continue_rounding = true;
0610 result[current_index] = '0';
0611 }
0612 else
0613 {
0614 continue_rounding = false;
0615 result[current_index] = static_cast<char>(result[current_index] + static_cast<char>(1));
0616 }
0617 } while (continue_rounding && current_index > 2);
0618 }
0619
0620
0621 if (fmt != chars_format::scientific)
0622 {
0623 while (result[index - 1] == '0')
0624 {
0625 --index;
0626 }
0627 }
0628 else
0629 {
0630
0631 if (precision + 1 > static_cast<int>(olength))
0632 {
0633 result[index - 1] = '0';
0634 }
0635 }
0636 }
0637 else if (static_cast<size_t>(precision) > index)
0638 {
0639
0640 return -1;
0641 }
0642 }
0643
0644
0645 result[index++] = 'e';
0646 int32_t exp = v.exponent + static_cast<int32_t>(olength) - 1;
0647 if (exp < 0)
0648 {
0649 result[index++] = '-';
0650 exp = -exp;
0651 }
0652 else
0653 {
0654 result[index++] = '+';
0655 }
0656
0657 uint32_t elength = static_cast<uint32_t>(num_digits(exp));
0658 for (uint32_t i = 0; i < elength; ++i)
0659 {
0660
0661 if (elength == 1)
0662 {
0663 result[index + elength - 1 - i] = '0';
0664 ++index;
0665 }
0666
0667 const uint32_t c = static_cast<uint32_t>(exp % 10);
0668 exp /= 10;
0669 result[index + elength - 1 - i] = static_cast<char>('0' + c);
0670 }
0671 if (elength == 0)
0672 {
0673 result[index++] = '0';
0674 result[index++] = '0';
0675 }
0676
0677 index += elength;
0678 return static_cast<int>(index);
0679 }
0680
0681 static inline struct floating_decimal_128 float_to_fd128(float f) noexcept
0682 {
0683 static_assert(sizeof(float) == sizeof(uint32_t), "Float is not 32 bits");
0684 uint32_t bits = 0;
0685 std::memcpy(&bits, &f, sizeof(float));
0686 return generic_binary_to_decimal(bits, 23, 8, false);
0687 }
0688
0689 static inline struct floating_decimal_128 double_to_fd128(double d) noexcept
0690 {
0691 static_assert(sizeof(double) == sizeof(uint64_t), "Double is not 64 bits");
0692 uint64_t bits = 0;
0693 std::memcpy(&bits, &d, sizeof(double));
0694 return generic_binary_to_decimal(bits, 52, 11, false);
0695 }
0696
0697
0698
0699 #ifdef BOOST_CHARCONV_HAS_FLOAT16
0700
0701 static inline struct floating_decimal_128 float16_t_to_fd128(std::float16_t f) noexcept
0702 {
0703 uint16_t bits = 0;
0704 std::memcpy(&bits, &f, sizeof(std::float16_t));
0705 return generic_binary_to_decimal(bits, 10, 5, false);
0706 }
0707
0708 #endif
0709
0710 #ifdef BOOST_CHARCONV_HAS_BRAINFLOAT16
0711
0712 static inline struct floating_decimal_128 float16_t_to_fd128(std::bfloat16_t f) noexcept
0713 {
0714 uint16_t bits = 0;
0715 std::memcpy(&bits, &f, sizeof(std::bfloat16_t));
0716 return generic_binary_to_decimal(bits, 7, 8, false);
0717 }
0718
0719 #endif
0720
0721 #if BOOST_CHARCONV_LDBL_BITS == 80
0722
0723 static inline struct floating_decimal_128 long_double_to_fd128(long double d) noexcept
0724 {
0725 #ifdef BOOST_CHARCONV_HAS_INT128
0726 unsigned_128_type bits = 0;
0727 std::memcpy(&bits, &d, sizeof(long double));
0728 #else
0729 trivial_uint128 trivial_bits;
0730 std::memcpy(&trivial_bits, &d, sizeof(long double));
0731 unsigned_128_type bits {trivial_bits};
0732 #endif
0733
0734 #ifdef BOOST_CHARCONV_DEBUG
0735
0736
0737
0738
0739 bits &= (one << 80) - 1;
0740 #endif
0741
0742 return generic_binary_to_decimal(bits, 64, 15, true);
0743 }
0744
0745 #elif BOOST_CHARCONV_LDBL_BITS == 128
0746
0747 static inline struct floating_decimal_128 long_double_to_fd128(long double d) noexcept
0748 {
0749 unsigned_128_type bits = 0;
0750 std::memcpy(&bits, &d, sizeof(long double));
0751
0752 #if LDBL_MANT_DIG == 113
0753 # ifdef __PPC64__
0754 return generic_binary_to_decimal(bits, 112, 15, false);
0755 # else
0756 return generic_binary_to_decimal(bits, 112, 15, true);
0757 # endif
0758 #elif LDBL_MANT_DIG == 106
0759 return generic_binary_to_decimal(bits, 105, 11, true);
0760 #endif
0761 }
0762
0763 #endif
0764
0765 }}}}
0766
0767 #endif