4848#include " src/__support/FPUtil/dyadic_float.h"
4949#include " src/__support/FPUtil/rounding_mode.h"
5050#include " src/__support/integer_to_string.h"
51+ #include " src/__support/libc_assert.h"
5152#include " src/__support/macros/config.h"
5253#include " src/stdio/printf_core/core_structs.h"
5354#include " src/stdio/printf_core/float_inf_nan_converter.h"
@@ -107,6 +108,14 @@ struct DigitsOutput {
107108 char digits[MAX_DIGITS + 1 ];
108109};
109110
111+ // Estimate log10 of a power of 2, by multiplying its exponent by
112+ // 1292913986/2^32. That is a rounded-down approximation to log10(2), accurate
113+ // enough that for any binary exponent in the range of float128 it will give
114+ // the correct value of floor(log10(2^n)).
115+ int estimate_log10 (int exponent_of_2) {
116+ return (exponent_of_2 * 1292913986LL ) >> 32 ;
117+ }
118+
110119// Calculate the actual digits of a decimal representation of an FP number.
111120//
112121// If `e_mode` is true, then `precision` indicates the desired number of output
@@ -139,22 +148,20 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
139148 return output;
140149 }
141150
142- // Estimate log10 of the input value, by multiplying its binary exponent by
143- // 1292913986/2^32. That is a rounded-down approximation to log10(2),
144- // accurate enough that for any binary exponent in the range of float128 it
145- // will give the correct value of floor(log10(2^n)).
151+ // Calculate bounds on log10 of the input value. Its binary exponent bounds
152+ // the value between two powers of 2, and we use estimate_log10 to determine
153+ // log10 of each of those.
146154 //
147- // This estimate is correct for deciding how many decimal digits we end up
148- // producing, unless a power of 10 falls in the interval corresponding to
149- // this binary exponent, in which case there might be one more decimal digit
150- // for larger mantissas. To detect this, we do the same computation for the
151- // next exponent up .
152- int log10_input_min = (( input.exponent - 1 ) * 1292913986LL ) >> 32 ;
153- int log10_input_max = (input.exponent * 1292913986LL ) >> 32 ;
155+ // If a power of 10 falls in the interval between those powers of 2, then
156+ // log10_input_min and log10_input_max will differ by 1, and the correct
157+ // decimal exponent of the output will be one of those two values. If no
158+ // power of 10 is in the interval, then these two values will be equal and
159+ // there is only one choice for the decimal exponent .
160+ int log10_input_min = estimate_log10 ( input.exponent - 1 );
161+ int log10_input_max = estimate_log10 (input.exponent ) ;
154162
155163 // Make a DyadicFloat containing the value 10, to use as the base for
156- // exponentation inside the following loop, potentially more than once if we
157- // need to iterate.
164+ // exponentiation.
158165 fputil::DyadicFloat<DF_BITS> ten (Sign::POS, 1 , 5 );
159166
160167 // Compute the exponent of the lowest-order digit we want as output. In F
@@ -213,6 +220,9 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
213220 // Convert the mantissa into a DyadicFloat, making sure it has the right
214221 // sign, so that directed rounding will go in the right direction, if
215222 // enabled.
223+ //
224+ // (The fixed -127 adjustment on the exponent is because input.mantissa is a
225+ // UInt128, and the leading 1 bit has been aligned to the top of it.)
216226 fputil::DyadicFloat<DF_BITS> flt_mantissa (input.sign , input.exponent - 127 ,
217227 input.mantissa );
218228
@@ -260,7 +270,7 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
260270 // X.YZe+NN and instead got WX.YZe+NN. So when we shorten the digit string
261271 // by one, we'll also need to increment the output exponent.
262272 if (output.ndigits > size_t (precision)) {
263- assert (output.ndigits == size_t (precision) + 1 );
273+ LIBC_ASSERT (output.ndigits == size_t (precision) + 1 );
264274 need_reround = true ;
265275 output.exponent ++;
266276 }
@@ -280,7 +290,7 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
280290 // one digit too long, or else we'd have spotted the problem in advance and
281291 // flipped into E mode already.
282292 if (output.ndigits > MAX_DIGITS) {
283- assert (output.ndigits == MAX_DIGITS + 1 );
293+ LIBC_ASSERT (output.ndigits == MAX_DIGITS + 1 );
284294 need_reround = true ;
285295 }
286296 }
@@ -318,9 +328,12 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
318328 // Extract the two relevant digits. round_digit is the one we're removing;
319329 // new_low_digit is the last one we're keeping, so we need to know if it's
320330 // even or odd to handle exact tie cases (when round_dir == 0).
321- int round_digit = output.digits [--output.ndigits ] - ' 0' ;
331+ --output.ndigits ;
332+ int round_digit = internal::b36_char_to_int (output.digits [output.ndigits ]);
322333 int new_low_digit =
323- output.ndigits == 0 ? 0 : output.digits [output.ndigits - 1 ] - ' 0' ;
334+ output.ndigits == 0
335+ ? 0
336+ : internal::b36_char_to_int (output.digits [output.ndigits - 1 ]);
324337
325338 // Make a binary number that we can pass to `fputil::rounding_direction`.
326339 // We put new_low_digit at bit 8, and imagine that we're rounding away the
@@ -330,6 +343,11 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
330343 //
331344 // Then we adjust by +1 or -1 based on round_dir if the round digit is 5,
332345 // as described above.
346+ //
347+ // The subexpression `(round_digit * 0x19a) >> 4` is computing the
348+ // expression (256/10 * round_digit) mentioned above, accurately enough to
349+ // map 5 to exactly 128 but avoiding an integer division (for platforms
350+ // where it's slow, e.g. not in hardware).
333351 LIBC_NAMESPACE::UInt<64 > round_word = (new_low_digit * 256 ) +
334352 ((round_digit * 0x19a ) >> 4 ) +
335353 (round_digit == 5 ? -round_dir : 0 );
@@ -343,9 +361,12 @@ DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
343361 // at a time. (A bit painful, but better than going back to the integer
344362 // we made it from and doing the decimal conversion all over again.)
345363 for (size_t i = output.ndigits ; i-- > 0 ;) {
346- if (output.digits [i]++ != ' 9' )
364+ if (output.digits [i] != ' 9' ) {
365+ output.digits [i]++;
347366 break ;
348- output.digits [i] = ' 0' ;
367+ } else {
368+ output.digits [i] = ' 0' ;
369+ }
349370 }
350371 }
351372 }
@@ -527,7 +548,7 @@ LIBC_INLINE int convert_float_inner(Writer *writer,
527548 radix::Dec::WithWidth<2 >::WithSign>
528549 expcvt{output.exponent };
529550 cpp::string_view expview = expcvt.view ();
530- expbuf[0 ] = (to_conv.conv_name & 32 ) | ' E' ;
551+ expbuf[0 ] = internal::islower (to_conv.conv_name ) ? ' e ' : ' E' ;
531552 explen = expview.size () + 1 ;
532553 __builtin_memcpy (expbuf + 1 , expview.data (), expview.size ());
533554 }
0 commit comments