• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Decimal Float Converter for printf ----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_H
10 #define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_H
11 
12 #include "src/__support/CPP/string_view.h"
13 #include "src/__support/FPUtil/FPBits.h"
14 #include "src/__support/FPUtil/rounding_mode.h"
15 #include "src/__support/big_int.h" // is_big_int_v
16 #include "src/__support/float_to_string.h"
17 #include "src/__support/integer_to_string.h"
18 #include "src/__support/libc_assert.h"
19 #include "src/stdio/printf_core/converter_utils.h"
20 #include "src/stdio/printf_core/core_structs.h"
21 #include "src/stdio/printf_core/float_inf_nan_converter.h"
22 #include "src/stdio/printf_core/writer.h"
23 
24 #include <inttypes.h>
25 #include <stddef.h>
26 
27 namespace LIBC_NAMESPACE {
28 namespace printf_core {
29 
30 using StorageType = fputil::FPBits<long double>::StorageType;
31 using DecimalString = IntegerToString<intmax_t>;
32 using ExponentString =
33     IntegerToString<intmax_t, radix::Dec::WithWidth<2>::WithSign>;
34 
35 // Returns true if value is divisible by 2^p.
36 template <typename T>
37 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_integral_v<T> || is_big_int_v<T>,
38                                        bool>
multiple_of_power_of_2(T value,uint32_t p)39 multiple_of_power_of_2(T value, uint32_t p) {
40   return (value & ((T(1) << p) - 1)) == 0;
41 }
42 
43 constexpr size_t BLOCK_SIZE = 9;
44 constexpr uint32_t MAX_BLOCK = 999999999;
45 
46 // constexpr size_t BLOCK_SIZE = 18;
47 // constexpr uint32_t MAX_BLOCK = 999999999999999999;
48 constexpr char DECIMAL_POINT = '.';
49 
get_round_direction(int last_digit,bool truncated,Sign sign)50 LIBC_INLINE RoundDirection get_round_direction(int last_digit, bool truncated,
51                                                Sign sign) {
52   switch (fputil::quick_get_round()) {
53   case FE_TONEAREST:
54     // Round to nearest, if it's exactly halfway then round to even.
55     if (last_digit != 5) {
56       return last_digit > 5 ? RoundDirection::Up : RoundDirection::Down;
57     } else {
58       return !truncated ? RoundDirection::Even : RoundDirection::Up;
59     }
60   case FE_DOWNWARD:
61     if (sign.is_neg() && (truncated || last_digit > 0)) {
62       return RoundDirection::Up;
63     } else {
64       return RoundDirection::Down;
65     }
66   case FE_UPWARD:
67     if (sign.is_pos() && (truncated || last_digit > 0)) {
68       return RoundDirection::Up;
69     } else {
70       return RoundDirection::Down;
71     }
72     return sign.is_neg() ? RoundDirection::Down : RoundDirection::Up;
73   case FE_TOWARDZERO:
74     return RoundDirection::Down;
75   default:
76     return RoundDirection::Down;
77   }
78 }
79 
80 template <typename T>
81 LIBC_INLINE constexpr cpp::enable_if_t<cpp::is_integral_v<T> || is_big_int_v<T>,
82                                        bool>
zero_after_digits(int32_t base_2_exp,int32_t digits_after_point,T mantissa,const int32_t mant_width)83 zero_after_digits(int32_t base_2_exp, int32_t digits_after_point, T mantissa,
84                   const int32_t mant_width) {
85   const int32_t required_twos = -base_2_exp - digits_after_point - 1;
86   // Add 8 to mant width since this is a loose bound.
87   const bool has_trailing_zeros =
88       required_twos <= 0 ||
89       (required_twos < (mant_width + 8) &&
90        multiple_of_power_of_2(mantissa, static_cast<uint32_t>(required_twos)));
91   return has_trailing_zeros;
92 }
93 
94 class PaddingWriter {
95   bool left_justified = false;
96   bool leading_zeroes = false;
97   char sign_char = 0;
98   size_t min_width = 0;
99 
100 public:
PaddingWriter()101   LIBC_INLINE PaddingWriter() {}
PaddingWriter(const FormatSection & to_conv,char init_sign_char)102   LIBC_INLINE PaddingWriter(const FormatSection &to_conv, char init_sign_char)
103       : left_justified((to_conv.flags & FormatFlags::LEFT_JUSTIFIED) > 0),
104         leading_zeroes((to_conv.flags & FormatFlags::LEADING_ZEROES) > 0),
105         sign_char(init_sign_char),
106         min_width(to_conv.min_width > 0 ? to_conv.min_width : 0) {}
107 
write_left_padding(Writer * writer,size_t total_digits)108   LIBC_INLINE int write_left_padding(Writer *writer, size_t total_digits) {
109     // The pattern is (spaces) (sign) (zeroes), but only one of spaces and
110     // zeroes can be written, and only if the padding amount is positive.
111     int padding_amount =
112         static_cast<int>(min_width - total_digits - (sign_char > 0 ? 1 : 0));
113     if (left_justified || padding_amount < 0) {
114       if (sign_char > 0) {
115         RET_IF_RESULT_NEGATIVE(writer->write(sign_char));
116       }
117       return 0;
118     }
119     if (!leading_zeroes) {
120       RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_amount));
121     }
122     if (sign_char > 0) {
123       RET_IF_RESULT_NEGATIVE(writer->write(sign_char));
124     }
125     if (leading_zeroes) {
126       RET_IF_RESULT_NEGATIVE(writer->write('0', padding_amount));
127     }
128     return 0;
129   }
130 
write_right_padding(Writer * writer,size_t total_digits)131   LIBC_INLINE int write_right_padding(Writer *writer, size_t total_digits) {
132     // If and only if the conversion is left justified, there may be trailing
133     // spaces.
134     int padding_amount =
135         static_cast<int>(min_width - total_digits - (sign_char > 0 ? 1 : 0));
136     if (left_justified && padding_amount > 0) {
137       RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_amount));
138     }
139     return 0;
140   }
141 };
142 
143 /*
144   We only need to round a given segment if all of the segments below it are
145   the max (or this is the last segment). This means that we don't have to
146   write those initially, we can just keep the most recent non-maximal
147   segment and a counter of the number of maximal segments. When we reach a
148   non-maximal segment, we write the stored segment as well as as many 9s as
149   are necessary. Alternately, if we reach the end and have to round up, then
150   we round the stored segment, and write zeroes following it. If this
151   crosses the decimal point, then we have to shift it one space to the
152   right.
153   This FloatWriter class does the buffering and counting, and writes to the
154   output when necessary.
155 */
156 class FloatWriter {
157   char block_buffer[BLOCK_SIZE]; // The buffer that holds a block.
158   size_t buffered_digits = 0;    // The number of digits held in the buffer.
159   bool has_written = false;      // True once any digits have been output.
160   size_t max_block_count = 0; // The # of blocks of all 9s currently buffered.
161   size_t total_digits = 0;    // The number of digits that will be output.
162   size_t digits_before_decimal = 0; // The # of digits to write before the '.'
163   size_t total_digits_written = 0;  // The # of digits that have been output.
164   bool has_decimal_point;           // True if the number has a decimal point.
165   Writer *writer;                   // Writes to the final output.
166   PaddingWriter padding_writer; // Handles prefixes/padding, uses total_digits.
167 
168   LIBC_INLINE int flush_buffer(bool round_up_max_blocks = false) {
169     const char MAX_BLOCK_DIGIT = (round_up_max_blocks ? '0' : '9');
170 
171     // Write the most recent buffered block, and mark has_written
172     if (!has_written) {
173       has_written = true;
174       RET_IF_RESULT_NEGATIVE(
175           padding_writer.write_left_padding(writer, total_digits));
176     }
177 
178     // if the decimal point is the next character, or is in the range covered
179     // by the buffered block, write the appropriate digits and the decimal
180     // point.
181     if (total_digits_written < digits_before_decimal &&
182         total_digits_written + buffered_digits >= digits_before_decimal &&
183         has_decimal_point) {
184       size_t digits_to_write = digits_before_decimal - total_digits_written;
185       if (digits_to_write > 0) {
186         // Write the digits before the decimal point.
187         RET_IF_RESULT_NEGATIVE(writer->write({block_buffer, digits_to_write}));
188       }
189       RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
190       if (buffered_digits - digits_to_write > 0) {
191         // Write the digits after the decimal point.
192         RET_IF_RESULT_NEGATIVE(
193             writer->write({block_buffer + digits_to_write,
194                            (buffered_digits - digits_to_write)}));
195       }
196       // add 1 for the decimal point
197       total_digits_written += buffered_digits + 1;
198       // Mark the buffer as empty.
199       buffered_digits = 0;
200     }
201 
202     // Clear the buffered digits.
203     if (buffered_digits > 0) {
204       RET_IF_RESULT_NEGATIVE(writer->write({block_buffer, buffered_digits}));
205       total_digits_written += buffered_digits;
206       buffered_digits = 0;
207     }
208 
209     // if the decimal point is the next character, or is in the range covered
210     // by the max blocks, write the appropriate digits and the decimal point.
211     if (total_digits_written < digits_before_decimal &&
212         total_digits_written + BLOCK_SIZE * max_block_count >=
213             digits_before_decimal &&
214         has_decimal_point) {
215       size_t digits_to_write = digits_before_decimal - total_digits_written;
216       if (digits_to_write > 0) {
217         RET_IF_RESULT_NEGATIVE(writer->write(MAX_BLOCK_DIGIT, digits_to_write));
218       }
219       RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
220       if ((BLOCK_SIZE * max_block_count) - digits_to_write > 0) {
221         RET_IF_RESULT_NEGATIVE(writer->write(
222             MAX_BLOCK_DIGIT, (BLOCK_SIZE * max_block_count) - digits_to_write));
223       }
224       // add 1 for the decimal point
225       total_digits_written += BLOCK_SIZE * max_block_count + 1;
226       // clear the buffer of max blocks
227       max_block_count = 0;
228     }
229 
230     // Clear the buffer of max blocks
231     if (max_block_count > 0) {
232       RET_IF_RESULT_NEGATIVE(
233           writer->write(MAX_BLOCK_DIGIT, max_block_count * BLOCK_SIZE));
234       total_digits_written += max_block_count * BLOCK_SIZE;
235       max_block_count = 0;
236     }
237     return 0;
238   }
239 
240   // -exponent will never overflow because all long double types we support
241   // have at most 15 bits of mantissa and the C standard defines an int as
242   // being at least 16 bits.
243   static_assert(fputil::FPBits<long double>::EXP_LEN < (sizeof(int) * 8));
244 
245 public:
FloatWriter(Writer * init_writer,bool init_has_decimal_point,const PaddingWriter & init_padding_writer)246   LIBC_INLINE FloatWriter(Writer *init_writer, bool init_has_decimal_point,
247                           const PaddingWriter &init_padding_writer)
248       : has_decimal_point(init_has_decimal_point), writer(init_writer),
249         padding_writer(init_padding_writer) {}
250 
init(size_t init_total_digits,size_t init_digits_before_decimal)251   LIBC_INLINE void init(size_t init_total_digits,
252                         size_t init_digits_before_decimal) {
253     total_digits = init_total_digits;
254     digits_before_decimal = init_digits_before_decimal;
255   }
256 
257   LIBC_INLINE void write_first_block(BlockInt block, bool exp_format = false) {
258     const DecimalString buf(block);
259     const cpp::string_view int_to_str = buf.view();
260     size_t digits_buffered = int_to_str.size();
261     // Block Buffer is guaranteed to not overflow since block cannot have more
262     // than BLOCK_SIZE digits.
263     // TODO: Replace with memcpy
264     for (size_t count = 0; count < digits_buffered; ++count) {
265       block_buffer[count] = int_to_str[count];
266     }
267     buffered_digits = digits_buffered;
268 
269     // In the exponent format (%e) we know how many digits will be written even
270     // before calculating any blocks, whereas the decimal format (%f) has to
271     // write all of the blocks that would come before the decimal place.
272     if (!exp_format) {
273       total_digits += digits_buffered;
274       digits_before_decimal += digits_buffered;
275     }
276   }
277 
write_middle_block(BlockInt block)278   LIBC_INLINE int write_middle_block(BlockInt block) {
279     if (block == MAX_BLOCK) { // Buffer max blocks in case of rounding
280       ++max_block_count;
281     } else { // If a non-max block has been found
282       RET_IF_RESULT_NEGATIVE(flush_buffer());
283 
284       // Now buffer the current block. We add 1 + MAX_BLOCK to force the
285       // leading zeroes, and drop the leading one. This is probably inefficient,
286       // but it works. See https://xkcd.com/2021/
287       const DecimalString buf(block + (MAX_BLOCK + 1));
288       const cpp::string_view int_to_str = buf.view();
289       // TODO: Replace with memcpy
290       for (size_t count = 0; count < BLOCK_SIZE; ++count) {
291         block_buffer[count] = int_to_str[count + 1];
292       }
293 
294       buffered_digits = BLOCK_SIZE;
295     }
296     return 0;
297   }
298 
299   LIBC_INLINE int write_last_block(BlockInt block, size_t block_digits,
300                                    RoundDirection round, int exponent = 0,
301                                    char exp_char = '\0') {
302     bool has_exp = (exp_char != '\0');
303 
304     char end_buff[BLOCK_SIZE];
305 
306     {
307       const DecimalString buf(block + (MAX_BLOCK + 1));
308       const cpp::string_view int_to_str = buf.view();
309 
310       // copy the last block_digits characters into the start of end_buff.
311       // TODO: Replace with memcpy
312       for (size_t count = 0; count < block_digits; ++count) {
313         end_buff[count] = int_to_str[count + 1 + (BLOCK_SIZE - block_digits)];
314       }
315     }
316 
317     char low_digit = '0';
318     if (block_digits > 0) {
319       low_digit = end_buff[block_digits - 1];
320     } else if (max_block_count > 0) {
321       low_digit = '9';
322     } else if (buffered_digits > 0) {
323       low_digit = block_buffer[buffered_digits - 1];
324     }
325 
326     bool round_up_max_blocks = false;
327 
328     // Round up
329     if (round == RoundDirection::Up ||
330         (round == RoundDirection::Even && low_digit % 2 != 0)) {
331       bool has_carry = true;
332       round_up_max_blocks = true; // if we're rounding up, we might need to
333                                   // round up the max blocks that are buffered.
334 
335       // handle the low block that we're adding
336       for (int count = static_cast<int>(block_digits) - 1;
337            count >= 0 && has_carry; --count) {
338         if (end_buff[count] == '9') {
339           end_buff[count] = '0';
340         } else {
341           end_buff[count] += 1;
342           has_carry = false;
343           round_up_max_blocks = false; // If the low block isn't all nines, then
344                                        // the max blocks aren't rounded up.
345         }
346       }
347       // handle the high block that's buffered
348       for (int count = static_cast<int>(buffered_digits) - 1;
349            count >= 0 && has_carry; --count) {
350         if (block_buffer[count] == '9') {
351           block_buffer[count] = '0';
352         } else {
353           block_buffer[count] += 1;
354           has_carry = false;
355         }
356       }
357 
358       // has_carry should only be true here if every previous digit is 9, which
359       // implies that the number has never been written.
360       if (has_carry /* && !has_written */) {
361         if (has_exp) { // This is in %e style
362           // Since this is exponential notation, we don't write any more digits
363           // but we do increment the exponent.
364           ++exponent;
365 
366           const ExponentString buf(exponent);
367           const cpp::string_view int_to_str = buf.view();
368 
369           // TODO: also change this to calculate the width of the number more
370           // efficiently.
371           size_t exponent_width = int_to_str.size();
372           size_t number_digits =
373               buffered_digits + (max_block_count * BLOCK_SIZE) + block_digits;
374 
375           // Here we have to recalculate the total number of digits since the
376           // exponent's width may have changed. We're only adding 1 to exponent
377           // width since exp_str appends the sign.
378           total_digits =
379               (has_decimal_point ? 1 : 0) + number_digits + 1 + exponent_width;
380 
381           // Normally write_left_padding is called by flush_buffer but since
382           // we're rounding up all of the digits, the ones in the buffer are
383           // wrong and can't be flushed.
384           RET_IF_RESULT_NEGATIVE(
385               padding_writer.write_left_padding(writer, total_digits));
386           // Now we know we need to print a leading 1, the decimal point, and
387           // then zeroes after it.
388           RET_IF_RESULT_NEGATIVE(writer->write('1'));
389           // digits_before_decimal - 1 to account for the leading '1'
390           if (has_decimal_point) {
391             RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
392             // This is just the length of the number, not including the decimal
393             // point, or exponent.
394 
395             if (number_digits > 1) {
396               RET_IF_RESULT_NEGATIVE(writer->write('0', number_digits - 1));
397             }
398           }
399           RET_IF_RESULT_NEGATIVE(writer->write(exp_char));
400           RET_IF_RESULT_NEGATIVE(writer->write(int_to_str));
401 
402           total_digits_written = total_digits;
403           return WRITE_OK;
404         } else { // This is in %f style
405           ++total_digits;
406           ++digits_before_decimal;
407           // Normally write_left_padding is called by flush_buffer but since
408           // we're rounding up all of the digits, the ones in the buffer are
409           // wrong and can't be flushed.
410           RET_IF_RESULT_NEGATIVE(
411               padding_writer.write_left_padding(writer, total_digits));
412           // Now we know we need to print a leading 1, zeroes up to the decimal
413           // point, the decimal point, and then finally digits after it.
414           RET_IF_RESULT_NEGATIVE(writer->write('1'));
415           // digits_before_decimal - 1 to account for the leading '1'
416           RET_IF_RESULT_NEGATIVE(writer->write('0', digits_before_decimal - 1));
417           if (has_decimal_point) {
418             RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
419             // add one to digits_before_decimal to account for the decimal point
420             // itself.
421             if (total_digits > digits_before_decimal + 1) {
422               RET_IF_RESULT_NEGATIVE(writer->write(
423                   '0', total_digits - (digits_before_decimal + 1)));
424             }
425           }
426           total_digits_written = total_digits;
427           return WRITE_OK;
428         }
429       }
430     }
431     // Either we intend to round down, or the rounding up is complete. Flush the
432     // buffers.
433 
434     RET_IF_RESULT_NEGATIVE(flush_buffer(round_up_max_blocks));
435 
436     // And then write the final block. It's written via the buffer so that if
437     // this is also the first block, the decimal point will be placed correctly.
438 
439     // TODO: Replace with memcpy
440     for (size_t count = 0; count < block_digits; ++count) {
441       block_buffer[count] = end_buff[count];
442     }
443     buffered_digits = block_digits;
444     RET_IF_RESULT_NEGATIVE(flush_buffer());
445 
446     if (has_exp) {
447       RET_IF_RESULT_NEGATIVE(writer->write(exp_char));
448       const ExponentString buf(exponent);
449       RET_IF_RESULT_NEGATIVE(writer->write(buf.view()));
450     }
451     total_digits_written = total_digits;
452 
453     return WRITE_OK;
454   }
455 
write_zeroes(uint32_t num_zeroes)456   LIBC_INLINE int write_zeroes(uint32_t num_zeroes) {
457     RET_IF_RESULT_NEGATIVE(flush_buffer());
458     RET_IF_RESULT_NEGATIVE(writer->write('0', num_zeroes));
459     return 0;
460   }
461 
right_pad()462   LIBC_INLINE int right_pad() {
463     return padding_writer.write_right_padding(writer, total_digits);
464   }
465 };
466 
467 // This implementation is based on the Ryu Printf algorithm by Ulf Adams:
468 // Ulf Adams. 2019. Ryū revisited: printf floating point conversion.
469 // Proc. ACM Program. Lang. 3, OOPSLA, Article 169 (October 2019), 23 pages.
470 // https://doi.org/10.1145/3360595
471 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
convert_float_decimal_typed(Writer * writer,const FormatSection & to_conv,fputil::FPBits<T> float_bits)472 LIBC_INLINE int convert_float_decimal_typed(Writer *writer,
473                                             const FormatSection &to_conv,
474                                             fputil::FPBits<T> float_bits) {
475   // signed because later we use -FRACTION_LEN
476   constexpr int32_t FRACTION_LEN = fputil::FPBits<T>::FRACTION_LEN;
477   int exponent = float_bits.get_explicit_exponent();
478 
479   char sign_char = 0;
480 
481   if (float_bits.is_neg())
482     sign_char = '-';
483   else if ((to_conv.flags & FormatFlags::FORCE_SIGN) == FormatFlags::FORCE_SIGN)
484     sign_char = '+'; // FORCE_SIGN has precedence over SPACE_PREFIX
485   else if ((to_conv.flags & FormatFlags::SPACE_PREFIX) ==
486            FormatFlags::SPACE_PREFIX)
487     sign_char = ' ';
488 
489   // If to_conv doesn't specify a precision, the precision defaults to 6.
490   const unsigned int precision = to_conv.precision < 0 ? 6 : to_conv.precision;
491   bool has_decimal_point =
492       (precision > 0) || ((to_conv.flags & FormatFlags::ALTERNATE_FORM) != 0);
493 
494   // nonzero is false until a nonzero digit is found. It is used to determine if
495   // leading zeroes should be printed, since before the first digit they are
496   // ignored.
497   bool nonzero = false;
498 
499   PaddingWriter padding_writer(to_conv, sign_char);
500   FloatWriter float_writer(writer, has_decimal_point, padding_writer);
501   FloatToString<T> float_converter(float_bits.get_val());
502 
503   const size_t positive_blocks = float_converter.get_positive_blocks();
504 
505   if (positive_blocks >= 0) {
506     // This loop iterates through the number a block at a time until it finds a
507     // block that is not zero or it hits the decimal point. This is because all
508     // zero blocks before the first nonzero digit or the decimal point are
509     // ignored (no leading zeroes, at least at this stage).
510     int32_t i = static_cast<int32_t>(positive_blocks) - 1;
511     for (; i >= 0; --i) {
512       BlockInt digits = float_converter.get_positive_block(i);
513       if (nonzero) {
514         RET_IF_RESULT_NEGATIVE(float_writer.write_middle_block(digits));
515       } else if (digits != 0) {
516         size_t blocks_before_decimal = i;
517         float_writer.init((blocks_before_decimal * BLOCK_SIZE) +
518                               (has_decimal_point ? 1 : 0) + precision,
519                           blocks_before_decimal * BLOCK_SIZE);
520         float_writer.write_first_block(digits);
521 
522         nonzero = true;
523       }
524     }
525   }
526 
527   // if we haven't yet found a valid digit, buffer a zero.
528   if (!nonzero) {
529     float_writer.init((has_decimal_point ? 1 : 0) + precision, 0);
530     float_writer.write_first_block(0);
531   }
532 
533   if (exponent < FRACTION_LEN) {
534     const uint32_t blocks = (precision / static_cast<uint32_t>(BLOCK_SIZE)) + 1;
535     uint32_t i = 0;
536     // if all the blocks we should write are zero
537     if (blocks <= float_converter.zero_blocks_after_point()) {
538       i = blocks; // just write zeroes up to precision
539       RET_IF_RESULT_NEGATIVE(float_writer.write_zeroes(precision));
540     } else if (i < float_converter.zero_blocks_after_point()) {
541       // else if there are some blocks that are zeroes
542       i = static_cast<uint32_t>(float_converter.zero_blocks_after_point());
543       // write those blocks as zeroes.
544       RET_IF_RESULT_NEGATIVE(float_writer.write_zeroes(9 * i));
545     }
546     // for each unwritten block
547     for (; i < blocks; ++i) {
548       if (float_converter.is_lowest_block(i)) {
549         const uint32_t fill = precision - 9 * i;
550         RET_IF_RESULT_NEGATIVE(float_writer.write_zeroes(fill));
551         break;
552       }
553       BlockInt digits = float_converter.get_negative_block(i);
554       if (i < blocks - 1) {
555         RET_IF_RESULT_NEGATIVE(float_writer.write_middle_block(digits));
556       } else {
557 
558         const uint32_t maximum =
559             static_cast<uint32_t>(precision - BLOCK_SIZE * i);
560         uint32_t last_digit = 0;
561         for (uint32_t k = 0; k < BLOCK_SIZE - maximum; ++k) {
562           last_digit = digits % 10;
563           digits /= 10;
564         }
565         RoundDirection round;
566         const bool truncated = !zero_after_digits(
567             exponent - FRACTION_LEN, precision,
568             float_bits.get_explicit_mantissa(), FRACTION_LEN);
569         round = get_round_direction(last_digit, truncated, float_bits.sign());
570 
571         RET_IF_RESULT_NEGATIVE(
572             float_writer.write_last_block(digits, maximum, round));
573         break;
574       }
575     }
576   } else {
577     RET_IF_RESULT_NEGATIVE(float_writer.write_zeroes(precision));
578   }
579   RET_IF_RESULT_NEGATIVE(float_writer.right_pad());
580   return WRITE_OK;
581 }
582 
583 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
convert_float_dec_exp_typed(Writer * writer,const FormatSection & to_conv,fputil::FPBits<T> float_bits)584 LIBC_INLINE int convert_float_dec_exp_typed(Writer *writer,
585                                             const FormatSection &to_conv,
586                                             fputil::FPBits<T> float_bits) {
587   // signed because later we use -FRACTION_LEN
588   constexpr int32_t FRACTION_LEN = fputil::FPBits<T>::FRACTION_LEN;
589   int exponent = float_bits.get_explicit_exponent();
590   StorageType mantissa = float_bits.get_explicit_mantissa();
591 
592   const char a = (to_conv.conv_name & 32) | 'A';
593 
594   char sign_char = 0;
595 
596   if (float_bits.is_neg())
597     sign_char = '-';
598   else if ((to_conv.flags & FormatFlags::FORCE_SIGN) == FormatFlags::FORCE_SIGN)
599     sign_char = '+'; // FORCE_SIGN has precedence over SPACE_PREFIX
600   else if ((to_conv.flags & FormatFlags::SPACE_PREFIX) ==
601            FormatFlags::SPACE_PREFIX)
602     sign_char = ' ';
603 
604   // If to_conv doesn't specify a precision, the precision defaults to 6.
605   const unsigned int precision = to_conv.precision < 0 ? 6 : to_conv.precision;
606   bool has_decimal_point =
607       (precision > 0) || ((to_conv.flags & FormatFlags::ALTERNATE_FORM) != 0);
608 
609   PaddingWriter padding_writer(to_conv, sign_char);
610   FloatWriter float_writer(writer, has_decimal_point, padding_writer);
611   FloatToString<T> float_converter(float_bits.get_val());
612 
613   size_t digits_written = 0;
614   int final_exponent = 0;
615 
616   // Here we would subtract 1 to account for the fact that block 0 counts as a
617   // positive block, but the loop below accounts for this by starting with
618   // subtracting 1 from cur_block.
619   int cur_block;
620 
621   if (exponent < 0) {
622     cur_block = -static_cast<int>(float_converter.zero_blocks_after_point());
623   } else {
624     cur_block = static_cast<int>(float_converter.get_positive_blocks());
625   }
626 
627   BlockInt digits = 0;
628 
629   // If the mantissa is 0, then the number is 0, meaning that looping until a
630   // non-zero block is found will loop forever. The first block is just 0.
631   if (mantissa != 0) {
632     // This loop finds the first block.
633     while (digits == 0) {
634       --cur_block;
635       digits = float_converter.get_block(cur_block);
636     }
637   } else {
638     cur_block = 0;
639   }
640 
641   const size_t block_width = IntegerToString<intmax_t>(digits).size();
642 
643   final_exponent = static_cast<int>(cur_block * BLOCK_SIZE) +
644                    static_cast<int>(block_width - 1);
645   int positive_exponent = final_exponent < 0 ? -final_exponent : final_exponent;
646 
647   size_t exponent_width = IntegerToString<intmax_t>(positive_exponent).size();
648 
649   // Calculate the total number of digits in the number.
650   // 1 - the digit before the decimal point
651   // 1 - the decimal point (optional)
652   // precision - the number of digits after the decimal point
653   // 1 - the 'e' at the start of the exponent
654   // 1 - the sign at the start of the exponent
655   // max(2, exp width) - the digits of the exponent, min 2.
656 
657   float_writer.init(1 + (has_decimal_point ? 1 : 0) + precision + 2 +
658                         (exponent_width < 2 ? 2 : exponent_width),
659                     1);
660 
661   // If this block is not the last block
662   if (block_width <= precision + 1) {
663     float_writer.write_first_block(digits, true);
664     digits_written += block_width;
665     --cur_block;
666   }
667 
668   // For each middle block.
669   for (; digits_written + BLOCK_SIZE < precision + 1; --cur_block) {
670     digits = float_converter.get_block(cur_block);
671 
672     RET_IF_RESULT_NEGATIVE(float_writer.write_middle_block(digits));
673     digits_written += BLOCK_SIZE;
674   }
675 
676   digits = float_converter.get_block(cur_block);
677 
678   size_t last_block_size = BLOCK_SIZE;
679 
680   // if the last block is also the first block, then ignore leading zeroes.
681   if (digits_written == 0) {
682     last_block_size = IntegerToString<intmax_t>(digits).size();
683   }
684 
685   // This tracks if the number is truncated, that meaning that the digits after
686   // last_digit are non-zero.
687   bool truncated = false;
688 
689   // This is the last block.
690   const size_t maximum = precision + 1 - digits_written;
691   uint32_t last_digit = 0;
692   for (uint32_t k = 0; k < last_block_size - maximum; ++k) {
693     if (last_digit > 0)
694       truncated = true;
695 
696     last_digit = digits % 10;
697     digits /= 10;
698   }
699 
700   // If the last block we read doesn't have the digit after the end of what
701   // we'll print, then we need to read the next block to get that digit.
702   if (maximum == last_block_size) {
703     --cur_block;
704     BlockInt extra_block = float_converter.get_block(cur_block);
705     last_digit = extra_block / ((MAX_BLOCK / 10) + 1);
706     if (extra_block % ((MAX_BLOCK / 10) + 1) > 0) {
707       truncated = true;
708     }
709   }
710 
711   RoundDirection round;
712 
713   // If we've already seen a truncated digit, then we don't need to check any
714   // more.
715   if (!truncated) {
716     // Check the blocks above the decimal point
717     if (cur_block >= 0) {
718       // Check every block until the decimal point for non-zero digits.
719       for (int cur_extra_block = cur_block - 1; cur_extra_block >= 0;
720            --cur_extra_block) {
721         BlockInt extra_block = float_converter.get_block(cur_extra_block);
722         if (extra_block > 0) {
723           truncated = true;
724           break;
725         }
726       }
727     }
728     // If it's still not truncated and there are digits below the decimal point
729     if (!truncated && exponent - FRACTION_LEN < 0) {
730       // Use the formula from %f.
731       truncated = !zero_after_digits(
732           exponent - FRACTION_LEN, precision - final_exponent,
733           float_bits.get_explicit_mantissa(), FRACTION_LEN);
734     }
735   }
736   round = get_round_direction(last_digit, truncated, float_bits.sign());
737 
738   RET_IF_RESULT_NEGATIVE(float_writer.write_last_block(
739       digits, maximum, round, final_exponent, a + 'E' - 'A'));
740 
741   RET_IF_RESULT_NEGATIVE(float_writer.right_pad());
742   return WRITE_OK;
743 }
744 
745 template <typename T, cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
convert_float_dec_auto_typed(Writer * writer,const FormatSection & to_conv,fputil::FPBits<T> float_bits)746 LIBC_INLINE int convert_float_dec_auto_typed(Writer *writer,
747                                              const FormatSection &to_conv,
748                                              fputil::FPBits<T> float_bits) {
749   // signed because later we use -FRACTION_LEN
750   constexpr int32_t FRACTION_LEN = fputil::FPBits<T>::FRACTION_LEN;
751   int exponent = float_bits.get_explicit_exponent();
752   StorageType mantissa = float_bits.get_explicit_mantissa();
753 
754   // From the standard: Let P (init_precision) equal the precision if nonzero, 6
755   // if the precision is omitted, or 1 if the precision is zero.
756   const unsigned int init_precision = to_conv.precision <= 0
757                                           ? (to_conv.precision == 0 ? 1 : 6)
758                                           : to_conv.precision;
759 
760   //  Then, if a conversion with style E would have an exponent of X
761   //  (base_10_exp):
762   int base_10_exp = 0;
763   // If P > X >= -4 the conversion is with style F and precision P - (X + 1).
764   // Otherwise, the conversion is with style E and precision P - 1.
765 
766   // For calculating the base 10 exponent, we need to process the number as if
767   // it has style E, so here we calculate the precision we'll use in that case.
768   const unsigned int exp_precision = init_precision - 1;
769 
770   FloatToString<T> float_converter(float_bits.get_val());
771 
772   // Here we would subtract 1 to account for the fact that block 0 counts as a
773   // positive block, but the loop below accounts for this by starting with
774   // subtracting 1 from cur_block.
775   int cur_block;
776 
777   if (exponent < 0) {
778     cur_block = -static_cast<int>(float_converter.zero_blocks_after_point());
779   } else {
780     cur_block = static_cast<int>(float_converter.get_positive_blocks());
781   }
782 
783   BlockInt digits = 0;
784 
785   // If the mantissa is 0, then the number is 0, meaning that looping until a
786   // non-zero block is found will loop forever.
787   if (mantissa != 0) {
788     // This loop finds the first non-zero block.
789     while (digits == 0) {
790       --cur_block;
791       digits = float_converter.get_block(cur_block);
792     }
793   } else {
794     // In the case of 0.0, then it's always decimal format. If we don't have alt
795     // form then the trailing zeroes are trimmed to make "0", else the precision
796     // is 1 less than specified by the user.
797     FormatSection new_conv = to_conv;
798     if ((to_conv.flags & FormatFlags::ALTERNATE_FORM) != 0) {
799       // This is a style F conversion, making the precision P - 1 - X, but since
800       // this is for the number 0, X (the base 10 exponent) is always 0.
801       new_conv.precision = init_precision - 1;
802     } else {
803       new_conv.precision = 0;
804     }
805     return convert_float_decimal_typed<T>(writer, new_conv, float_bits);
806   }
807 
808   const size_t block_width = IntegerToString<intmax_t>(digits).size();
809 
810   size_t digits_checked = 0;
811   // TODO: look into unifying trailing_zeroes and trailing_nines. The number can
812   // end in a nine or a zero, but not both.
813   size_t trailing_zeroes = 0;
814   size_t trailing_nines = 0;
815 
816   base_10_exp = static_cast<int>(cur_block * BLOCK_SIZE) +
817                 static_cast<int>(block_width - 1);
818 
819   // If the first block is not also the last block
820   if (block_width <= exp_precision + 1) {
821     const DecimalString buf(digits);
822     const cpp::string_view int_to_str = buf.view();
823 
824     for (size_t i = 0; i < block_width; ++i) {
825       if (int_to_str[i] == '9') {
826         ++trailing_nines;
827         trailing_zeroes = 0;
828       } else if (int_to_str[i] == '0') {
829         ++trailing_zeroes;
830         trailing_nines = 0;
831       } else {
832         trailing_nines = 0;
833         trailing_zeroes = 0;
834       }
835     }
836     digits_checked += block_width;
837     --cur_block;
838   }
839 
840   // Handle middle blocks
841   for (; digits_checked + BLOCK_SIZE < exp_precision + 1; --cur_block) {
842     digits = float_converter.get_block(cur_block);
843     digits_checked += BLOCK_SIZE;
844     if (digits == MAX_BLOCK) {
845       trailing_nines += 9;
846       trailing_zeroes = 0;
847     } else if (digits == 0) {
848       trailing_zeroes += 9;
849       trailing_nines = 0;
850     } else {
851       // The block is neither all nines nor all zeroes, so we need to figure out
852       // what it ends with.
853       trailing_nines = 0;
854       trailing_zeroes = 0;
855       BlockInt copy_of_digits = digits;
856       BlockInt cur_last_digit = copy_of_digits % 10;
857       // We only care if it ends in nines or zeroes.
858       while (copy_of_digits > 0 &&
859              (cur_last_digit == 9 || cur_last_digit == 0)) {
860         // If the next digit is not the same as the previous one, then there are
861         // no more contiguous trailing digits.
862         if (copy_of_digits % 10 != cur_last_digit) {
863           break;
864         }
865         if (cur_last_digit == 9) {
866           ++trailing_nines;
867         } else if (cur_last_digit == 0) {
868           ++trailing_zeroes;
869         } else {
870           break;
871         }
872         copy_of_digits /= 10;
873       }
874     }
875   }
876 
877   // Handle the last block
878 
879   digits = float_converter.get_block(cur_block);
880 
881   size_t last_block_size = BLOCK_SIZE;
882 
883   const DecimalString buf(digits);
884   const cpp::string_view int_to_str = buf.view();
885 
886   size_t implicit_leading_zeroes = BLOCK_SIZE - int_to_str.size();
887 
888   // if the last block is also the first block, then ignore leading zeroes.
889   if (digits_checked == 0) {
890     last_block_size = int_to_str.size();
891     implicit_leading_zeroes = 0;
892   }
893 
894   unsigned int digits_requested =
895       (exp_precision + 1) - static_cast<unsigned int>(digits_checked);
896 
897   int digits_to_check =
898       digits_requested - static_cast<int>(implicit_leading_zeroes);
899   if (digits_to_check < 0) {
900     digits_to_check = 0;
901   }
902 
903   // If the block is not the maximum size, that means it has leading
904   // zeroes, and zeroes are not nines.
905   if (implicit_leading_zeroes > 0) {
906     trailing_nines = 0;
907   }
908 
909   // But leading zeroes are zeroes (that could be trailing). We take the
910   // minimum of the leading zeroes and digits requested because if there are
911   // more requested digits than leading zeroes we shouldn't count those.
912   trailing_zeroes +=
913       (implicit_leading_zeroes > digits_requested ? digits_requested
914                                                   : implicit_leading_zeroes);
915 
916   // Check the upper digits of this block.
917   for (int i = 0; i < digits_to_check; ++i) {
918     if (int_to_str[i] == '9') {
919       ++trailing_nines;
920       trailing_zeroes = 0;
921     } else if (int_to_str[i] == '0') {
922       ++trailing_zeroes;
923       trailing_nines = 0;
924     } else {
925       trailing_nines = 0;
926       trailing_zeroes = 0;
927     }
928   }
929 
930   bool truncated = false;
931 
932   // Find the digit after the lowest digit that we'll actually print to
933   // determine the rounding.
934   const uint32_t maximum =
935       exp_precision + 1 - static_cast<uint32_t>(digits_checked);
936   uint32_t last_digit = 0;
937   for (uint32_t k = 0; k < last_block_size - maximum; ++k) {
938     if (last_digit > 0)
939       truncated = true;
940 
941     last_digit = digits % 10;
942     digits /= 10;
943   }
944 
945   // If the last block we read doesn't have the digit after the end of what
946   // we'll print, then we need to read the next block to get that digit.
947   if (maximum == last_block_size) {
948     --cur_block;
949     BlockInt extra_block = float_converter.get_block(cur_block);
950     last_digit = extra_block / ((MAX_BLOCK / 10) + 1);
951 
952     if (extra_block % ((MAX_BLOCK / 10) + 1) > 0)
953       truncated = true;
954   }
955 
956   // TODO: unify this code across the three float conversions.
957   RoundDirection round;
958 
959   // If we've already seen a truncated digit, then we don't need to check any
960   // more.
961   if (!truncated) {
962     // Check the blocks above the decimal point
963     if (cur_block >= 0) {
964       // Check every block until the decimal point for non-zero digits.
965       for (int cur_extra_block = cur_block - 1; cur_extra_block >= 0;
966            --cur_extra_block) {
967         BlockInt extra_block = float_converter.get_block(cur_extra_block);
968         if (extra_block > 0) {
969           truncated = true;
970           break;
971         }
972       }
973     }
974     // If it's still not truncated and there are digits below the decimal point
975     if (!truncated && exponent - FRACTION_LEN < 0) {
976       // Use the formula from %f.
977       truncated = !zero_after_digits(
978           exponent - FRACTION_LEN, exp_precision - base_10_exp,
979           float_bits.get_explicit_mantissa(), FRACTION_LEN);
980     }
981   }
982 
983   round = get_round_direction(last_digit, truncated, float_bits.sign());
984 
985   bool round_up;
986   if (round == RoundDirection::Up) {
987     round_up = true;
988   } else if (round == RoundDirection::Down) {
989     round_up = false;
990   } else {
991     // RoundDirection is even, so check the lowest digit that will be printed.
992     uint32_t low_digit;
993 
994     // maximum is the number of digits that will remain in digits after getting
995     // last_digit. If it's greater than zero, we can just check the lowest digit
996     // in digits.
997     if (maximum > 0) {
998       low_digit = digits % 10;
999     } else {
1000       // Else if there are trailing nines, then the low digit is a nine, same
1001       // with zeroes.
1002       if (trailing_nines > 0) {
1003         low_digit = 9;
1004       } else if (trailing_zeroes > 0) {
1005         low_digit = 0;
1006       } else {
1007         // If there are no trailing zeroes or nines, then the round direction
1008         // doesn't actually matter here. Since this conversion passes off the
1009         // value to another one for final conversion, rounding only matters to
1010         // determine if the exponent is higher than expected (with an all nine
1011         // number) or to determine the trailing zeroes to trim. In this case
1012         // low_digit is set to 0, but it could be set to any number.
1013 
1014         low_digit = 0;
1015       }
1016     }
1017     round_up = (low_digit % 2) != 0;
1018   }
1019 
1020   digits_checked += digits_requested;
1021   LIBC_ASSERT(digits_checked == init_precision);
1022   // At this point we should have checked all the digits requested by the
1023   // precision. We may increment this number 1 more if we round up all of the
1024   // digits, but at this point in the code digits_checked should always equal
1025   // init_precision.
1026 
1027   if (round_up) {
1028     // If all the digits that would be printed are nines, then rounding up means
1029     // that the base 10 exponent is one higher and all those nines turn to
1030     // zeroes (e.g. 999 -> 1000).
1031     if (trailing_nines == init_precision) {
1032       ++base_10_exp;
1033       trailing_zeroes = digits_checked;
1034       ++digits_checked;
1035     } else {
1036       // If there are trailing nines, they turn into trailing zeroes when
1037       // they're rounded up.
1038       if (trailing_nines > 0) {
1039         trailing_zeroes += trailing_nines;
1040       } else if (trailing_zeroes > 0) {
1041         // If there are trailing zeroes, then the last digit will be rounded up
1042         // to a 1 so they aren't trailing anymore.
1043         trailing_zeroes = 0;
1044       }
1045     }
1046   }
1047 
1048   // if P > X >= -4, the conversion is with style f (or F) and precision equals
1049   //  P - (X + 1).
1050   if (static_cast<int>(init_precision) > base_10_exp && base_10_exp >= -4) {
1051     FormatSection new_conv = to_conv;
1052     const int conv_precision = init_precision - (base_10_exp + 1);
1053 
1054     if ((to_conv.flags & FormatFlags::ALTERNATE_FORM) != 0) {
1055       new_conv.precision = conv_precision;
1056     } else {
1057       // If alt form isn't set, then we need to determine the number of trailing
1058       // zeroes and set the precision such that they are removed.
1059 
1060       /*
1061       Here's a diagram of an example:
1062 
1063       printf("%.15g", 22.25);
1064 
1065                             +--- init_precision = 15
1066                             |
1067                             +-------------------+
1068                             |                   |
1069                             |  ++--- trimmed_precision = 2
1070                             |  ||               |
1071                             22.250000000000000000
1072                             ||   |              |
1073                             ++   +--------------+
1074                              |   |
1075        base_10_exp + 1 = 2 --+   +--- trailing_zeroes = 11
1076       */
1077       int trimmed_precision = static_cast<int>(
1078           digits_checked - (base_10_exp + 1) - trailing_zeroes);
1079       if (trimmed_precision < 0) {
1080         trimmed_precision = 0;
1081       }
1082       new_conv.precision = (trimmed_precision > conv_precision)
1083                                ? conv_precision
1084                                : trimmed_precision;
1085     }
1086 
1087     return convert_float_decimal_typed<T>(writer, new_conv, float_bits);
1088   } else {
1089     // otherwise, the conversion is with style e (or E) and precision equals
1090     // P - 1
1091     const int conv_precision = init_precision - 1;
1092     FormatSection new_conv = to_conv;
1093     if ((to_conv.flags & FormatFlags::ALTERNATE_FORM) != 0) {
1094       new_conv.precision = conv_precision;
1095     } else {
1096       // If alt form isn't set, then we need to determine the number of trailing
1097       // zeroes and set the precision such that they are removed.
1098       int trimmed_precision =
1099           static_cast<int>(digits_checked - 1 - trailing_zeroes);
1100       if (trimmed_precision < 0) {
1101         trimmed_precision = 0;
1102       }
1103       new_conv.precision = (trimmed_precision > conv_precision)
1104                                ? conv_precision
1105                                : trimmed_precision;
1106     }
1107     return convert_float_dec_exp_typed<T>(writer, new_conv, float_bits);
1108   }
1109 }
1110 
1111 // TODO: unify the float converters to remove the duplicated checks for inf/nan.
convert_float_decimal(Writer * writer,const FormatSection & to_conv)1112 LIBC_INLINE int convert_float_decimal(Writer *writer,
1113                                       const FormatSection &to_conv) {
1114   if (to_conv.length_modifier == LengthModifier::L) {
1115     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
1116     fputil::FPBits<long double> float_bits(float_raw);
1117     if (!float_bits.is_inf_or_nan()) {
1118       return convert_float_decimal_typed<long double>(writer, to_conv,
1119                                                       float_bits);
1120     }
1121   } else {
1122     fputil::FPBits<double>::StorageType float_raw =
1123         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
1124     fputil::FPBits<double> float_bits(float_raw);
1125     if (!float_bits.is_inf_or_nan()) {
1126       return convert_float_decimal_typed<double>(writer, to_conv, float_bits);
1127     }
1128   }
1129 
1130   return convert_inf_nan(writer, to_conv);
1131 }
1132 
convert_float_dec_exp(Writer * writer,const FormatSection & to_conv)1133 LIBC_INLINE int convert_float_dec_exp(Writer *writer,
1134                                       const FormatSection &to_conv) {
1135   if (to_conv.length_modifier == LengthModifier::L) {
1136     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
1137     fputil::FPBits<long double> float_bits(float_raw);
1138     if (!float_bits.is_inf_or_nan()) {
1139       return convert_float_dec_exp_typed<long double>(writer, to_conv,
1140                                                       float_bits);
1141     }
1142   } else {
1143     fputil::FPBits<double>::StorageType float_raw =
1144         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
1145     fputil::FPBits<double> float_bits(float_raw);
1146     if (!float_bits.is_inf_or_nan()) {
1147       return convert_float_dec_exp_typed<double>(writer, to_conv, float_bits);
1148     }
1149   }
1150 
1151   return convert_inf_nan(writer, to_conv);
1152 }
1153 
convert_float_dec_auto(Writer * writer,const FormatSection & to_conv)1154 LIBC_INLINE int convert_float_dec_auto(Writer *writer,
1155                                        const FormatSection &to_conv) {
1156   if (to_conv.length_modifier == LengthModifier::L) {
1157     fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
1158     fputil::FPBits<long double> float_bits(float_raw);
1159     if (!float_bits.is_inf_or_nan()) {
1160       return convert_float_dec_auto_typed<long double>(writer, to_conv,
1161                                                        float_bits);
1162     }
1163   } else {
1164     fputil::FPBits<double>::StorageType float_raw =
1165         static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
1166     fputil::FPBits<double> float_bits(float_raw);
1167     if (!float_bits.is_inf_or_nan()) {
1168       return convert_float_dec_auto_typed<double>(writer, to_conv, float_bits);
1169     }
1170   }
1171 
1172   return convert_inf_nan(writer, to_conv);
1173 }
1174 
1175 } // namespace printf_core
1176 } // namespace LIBC_NAMESPACE
1177 
1178 #endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_H
1179