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> |
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 | |
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> |
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: |
101 | LIBC_INLINE PaddingWriter() {} |
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 | |
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 | |
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: |
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 | |
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 | |
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 | |
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 | |
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> |
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(init_total_digits: (blocks_before_decimal * BLOCK_SIZE) + |
518 | (has_decimal_point ? 1 : 0) + precision, |
519 | init_digits_before_decimal: blocks_before_decimal * BLOCK_SIZE); |
520 | float_writer.write_first_block(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(init_total_digits: (has_decimal_point ? 1 : 0) + precision, init_digits_before_decimal: 0); |
530 | float_writer.write_first_block(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> |
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(init_total_digits: 1 + (has_decimal_point ? 1 : 0) + precision + 2 + |
658 | (exponent_width < 2 ? 2 : exponent_width), |
659 | init_digits_before_decimal: 1); |
660 | |
661 | // If this block is not the last block |
662 | if (block_width <= precision + 1) { |
663 | float_writer.write_first_block(block: digits, exp_format: 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 = 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_block - 1; cur_extra_block >= 0; |
720 | --cur_extra_block) { |
721 | BlockInt = 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> |
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 = 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_block - 1; cur_extra_block >= 0; |
966 | --cur_extra_block) { |
967 | BlockInt = 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. |
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 | |
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 | |
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 | |