| 960 | // https://fmt.dev/p372-steele.pdf. |
| 961 | template <typename Double> |
| 962 | void fallback_format(Double d, buffer<char>& buf, int& exp10) { |
| 963 | bigint numerator; // 2 * R in (FPP)^2. |
| 964 | bigint denominator; // 2 * S in (FPP)^2. |
| 965 | // lower and upper are differences between value and corresponding boundaries. |
| 966 | bigint lower; // (M^- in (FPP)^2). |
| 967 | bigint upper_store; // upper's value if different from lower. |
| 968 | bigint* upper = nullptr; // (M^+ in (FPP)^2). |
| 969 | fp value; |
| 970 | // Shift numerator and denominator by an extra bit or two (if lower boundary |
| 971 | // is closer) to make lower and upper integers. This eliminates multiplication |
| 972 | // by 2 during later computations. |
| 973 | // TODO: handle float |
| 974 | int shift = value.assign(d) ? 2 : 1; |
| 975 | uint64_t significand = value.f << shift; |
| 976 | if (value.e >= 0) { |
| 977 | numerator.assign(significand); |
| 978 | numerator <<= value.e; |
| 979 | lower.assign(1); |
| 980 | lower <<= value.e; |
| 981 | if (shift != 1) { |
| 982 | upper_store.assign(1); |
| 983 | upper_store <<= value.e + 1; |
| 984 | upper = &upper_store; |
| 985 | } |
| 986 | denominator.assign_pow10(exp10); |
| 987 | denominator <<= 1; |
| 988 | } else if (exp10 < 0) { |
| 989 | numerator.assign_pow10(-exp10); |
| 990 | lower.assign(numerator); |
| 991 | if (shift != 1) { |
| 992 | upper_store.assign(numerator); |
| 993 | upper_store <<= 1; |
| 994 | upper = &upper_store; |
| 995 | } |
| 996 | numerator *= significand; |
| 997 | denominator.assign(1); |
| 998 | denominator <<= shift - value.e; |
| 999 | } else { |
| 1000 | numerator.assign(significand); |
| 1001 | denominator.assign_pow10(exp10); |
| 1002 | denominator <<= shift - value.e; |
| 1003 | lower.assign(1); |
| 1004 | if (shift != 1) { |
| 1005 | upper_store.assign(1ULL << 1); |
| 1006 | upper = &upper_store; |
| 1007 | } |
| 1008 | } |
| 1009 | if (!upper) upper = &lower; |
| 1010 | // Invariant: value == (numerator / denominator) * pow(10, exp10). |
| 1011 | bool even = (value.f & 1) == 0; |
| 1012 | int num_digits = 0; |
| 1013 | char* data = buf.data(); |
| 1014 | for (;;) { |
| 1015 | int digit = numerator.divmod_assign(denominator); |
| 1016 | bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. |
| 1017 | // numerator + upper >[=] pow10: |
| 1018 | bool high = add_compare(numerator, *upper, denominator) + even > 0; |
| 1019 | data[num_digits++] = static_cast<char>('0' + digit); |
no test coverage detected