Warning: This file is not a C or C++ file. It does not have highlighting.

1//===-- Decimal Float Converter for printf (320-bit float) ------*- 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// This file implements an alternative to the Ryū printf algorithm in
10// float_dec_converter.h. Instead of generating output digits 9 at a time on
11// demand, in this implementation, a float is converted to decimal by computing
12// just one power of 10 and multiplying/dividing the entire input by it,
13// generating the whole string of decimal output digits in one go.
14//
15// This avoids the large constant lookup table of Ryū, making it more suitable
16// for low-memory embedded contexts; but it's also faster than the fallback
17// version of Ryū which computes table entries on demand using DyadicFloat,
18// because those must calculate a potentially large power of 10 per 9-digit
19// output block, whereas this computes just one, which does the whole job.
20//
21// The calculation is done in 320-bit DyadicFloat, which provides enough
22// precision to generate 39 correct digits of output from any floating-point
23// size up to and including 128-bit long double, because the rounding errors in
24// computing the largest necessary power of 10 are still smaller than the
25// distance (in the 320-bit float format) between adjacent 39-decimal-digit
26// outputs.
27//
28// No further digits beyond the 39th are generated: if the printf format string
29// asks for more precision than that, the answer is padded with 0s. This is a
30// permitted option in IEEE 754-2019 (section 5.12.2): you're allowed to define
31// a limit H on the number of decimal digits you can generate, and pad with 0s
32// if asked for more than that, subject to the constraint that H must be
33// consistent across all float formats you support (you can't use a smaller H
34// for single precision than double or long double), and must be large enough
35// that even in the largest supported precision the only numbers misrounded are
36// ones extremely close to a rounding boundary. 39 digits is the smallest
37// permitted value for an implementation supporting binary128.
38//
39//===----------------------------------------------------------------------===//
40
41#ifndef LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_LIMITED_H
42#define LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_LIMITED_H
43
44#include "src/__support/CPP/algorithm.h"
45#include "src/__support/CPP/string.h"
46#include "src/__support/CPP/string_view.h"
47#include "src/__support/FPUtil/FPBits.h"
48#include "src/__support/FPUtil/dyadic_float.h"
49#include "src/__support/FPUtil/rounding_mode.h"
50#include "src/__support/integer_to_string.h"
51#include "src/__support/libc_assert.h"
52#include "src/__support/macros/config.h"
53#include "src/stdio/printf_core/core_structs.h"
54#include "src/stdio/printf_core/float_inf_nan_converter.h"
55#include "src/stdio/printf_core/writer.h"
56
57namespace LIBC_NAMESPACE_DECL {
58namespace printf_core {
59
60enum class ConversionType { E, F, G };
61using StorageType = fputil::FPBits<long double>::StorageType;
62
63constexpr unsigned MAX_DIGITS = 39;
64constexpr size_t DF_BITS = 320;
65constexpr char DECIMAL_POINT = '.';
66
67struct DigitsInput {
68 // Input mantissa, stored with the explicit leading 1 bit (if any) at the
69 // top. So either it has a value in the range [2^127,2^128) representing a
70 // real number in [1,2), or it has the value 0, representing 0.
71 UInt128 mantissa;
72
73 // Input exponent, as a power of 2 to multiply into mantissa.
74 int exponent;
75
76 // Input sign.
77 Sign sign;
78
79 // Constructor which accepts a mantissa direct from a floating-point format,
80 // and shifts it up to the top of the UInt128 so that a function consuming
81 // this struct afterwards doesn't have to remember which format it came from.
82 DigitsInput(int32_t fraction_len, StorageType mantissa_, int exponent_,
83 Sign sign)
84 : mantissa(UInt128(mantissa_) << (127 - fraction_len)),
85 exponent(exponent_), sign(sign) {
86 if (!(mantissa & (UInt128(1) << 127)) && mantissa != 0) {
87 // Normalize a denormalized input.
88 int shift = cpp::countl_zero(mantissa);
89 mantissa <<= shift;
90 exponent -= shift;
91 }
92 }
93};
94
95struct DigitsOutput {
96 // Output from decimal_digits().
97 //
98 // `digits` is a buffer containing nothing but ASCII digits. Even if the
99 // decimal point needs to appear somewhere in the final output string, it
100 // isn't represented in _this_ string; the client of this object will insert
101 // it in an appropriate place. `ndigits` gives the buffer size.
102 //
103 // `exponent` represents the exponent you would display if the decimal point
104 // comes after the first digit of decimal_digits, e.g. if digits == "1234"
105 // and exponent = 3 then this represents 1.234e3, or just the integer 1234.
106 size_t ndigits;
107 int exponent;
108 char digits[MAX_DIGITS + 1];
109};
110
111// Estimate log10 of a power of 2, by multiplying its exponent by
112// 1292913986/2^32. That is a rounded-down approximation to log10(2), accurate
113// enough that for any binary exponent in the range of float128 it will give
114// the correct value of floor(log10(2^n)).
115LIBC_INLINE int estimate_log10(int exponent_of_2) {
116 return static_cast<int>((exponent_of_2 * 1292913986LL) >> 32);
117}
118
119// Calculate the actual digits of a decimal representation of an FP number.
120//
121// If `e_mode` is true, then `precision` indicates the desired number of output
122// decimal digits. On return, `decimal_digits` will be a string of length
123// exactly `precision` starting with a nonzero digit; `decimal_exponent` will
124// be filled in to indicate the exponent as shown above.
125//
126// If `e_mode` is false, then `precision` indicates the desired number of
127// digits after the decimal point. On return, the last digit in the string
128// `decimal_digits` has a place value of _at least_ 10^-precision. But also, at
129// most `MAX_DIGITS` digits are returned, so the caller may need to pad it at
130// the end with the appropriate number of extra 0s.
131LIBC_INLINE
132DigitsOutput decimal_digits(DigitsInput input, int precision, bool e_mode) {
133 if (input.mantissa == 0) {
134 // Special-case zero, by manually generating the right number of zero
135 // digits and setting an appropriate exponent.
136 DigitsOutput output;
137 if (!e_mode) {
138 // In F mode, it's enough to return an empty string of digits. That's the
139 // same thing we do when given a nonzero number that rounds down to 0.
140 output.ndigits = 0;
141 output.exponent = -precision - 1;
142 } else {
143 // In E mode, generate a string containing the expected number of 0s.
144 __builtin_memset(output.digits, '0', precision);
145 output.ndigits = precision;
146 output.exponent = 0;
147 }
148 return output;
149 }
150
151 // Calculate bounds on log10 of the input value. Its binary exponent bounds
152 // the value between two powers of 2, and we use estimate_log10 to determine
153 // log10 of each of those.
154 //
155 // If a power of 10 falls in the interval between those powers of 2, then
156 // log10_input_min and log10_input_max will differ by 1, and the correct
157 // decimal exponent of the output will be one of those two values. If no
158 // power of 10 is in the interval, then these two values will be equal and
159 // there is only one choice for the decimal exponent.
160 int log10_input_min = estimate_log10(input.exponent - 1);
161 int log10_input_max = estimate_log10(input.exponent);
162
163 // Make a DyadicFloat containing the value 10, to use as the base for
164 // exponentiation.
165 fputil::DyadicFloat<DF_BITS> ten(Sign::POS, 1, 5);
166
167 // Compute the exponent of the lowest-order digit we want as output. In F
168 // mode this depends only on the desired precision. In E mode it's based on
169 // log10_input, which is (an estimate of) the exponent corresponding to the
170 // _high_-order decimal digit of the number.
171 int log10_low_digit = e_mode ? log10_input_min + 1 - precision : -precision;
172
173 // The general plan is to calculate an integer whose decimal representation
174 // is precisely the string of output digits, by doing a DyadicFloat
175 // computation of (input_mantissa / 10^(log10_low_digit)) and then rounding
176 // that to an integer.
177 //
178 // The number of output decimal digits (if the mathematical result of this
179 // operation were computed without overflow) will be one of these:
180 // (log10_input_min - log10_low_digit + 1)
181 // (log10_input_max - log10_low_digit + 1)
182 //
183 // In E mode, this means we'll either get the correct number of output digits
184 // immediately, or else one too many (in which case we can correct for that
185 // at the rounding stage). But in F mode, if the number is very large
186 // compared to the number of decimal places the user asked for, we might be
187 // about to generate far too many digits and overflow our float format. In
188 // that case, reset to E mode immediately, to avoid having to detect the
189 // overflow _after_ the multiplication and retry. So if even the smaller
190 // number of possible output digits is too many, we might as well change our
191 // mind right now and switch into E mode.
192 if (log10_input_max - log10_low_digit + 1 > int(MAX_DIGITS)) {
193 precision = MAX_DIGITS;
194 e_mode = true;
195 log10_low_digit = log10_input_min + 1 - precision;
196 }
197
198 // Now actually calculate (input_mantissa / 10^(log10_low_digit)).
199 //
200 // If log10_low_digit < 0, then we calculate 10^(-log10_low_digit) and
201 // multiply by it instead, so that the exponent is non-negative in all cases.
202 // This ensures that the power of 10 is always mathematically speaking an
203 // integer, so that it can be represented exactly in binary (without a
204 // recurring fraction), and when it's small enough to fit in DF_BITS,
205 // fputil::pow_n should return the exact answer, and then
206 // fputil::rounded_{div,mul} will introduce only the unavoidable rounding
207 // error of up to 1/2 ULP.
208 //
209 // Beyond that point, pow_n will be imprecise. But DF_BITS is set high enough
210 // that even for the most difficult cases in 128-bit long double, the extra
211 // precision in the calculation is enough to ensure we still get the right
212 // answer.
213 //
214 // If the output integer doesn't fit in DF_BITS, we set the `overflow` flag.
215
216 // Calculate the power of 10 to divide or multiply by.
217 fputil::DyadicFloat<DF_BITS> power_of_10 =
218 fputil::pow_n(ten, cpp::abs(log10_low_digit));
219
220 // Convert the mantissa into a DyadicFloat, making sure it has the right
221 // sign, so that directed rounding will go in the right direction, if
222 // enabled.
223 fputil::DyadicFloat<DF_BITS> flt_mantissa(
224 input.sign,
225 input.exponent -
226 (cpp::numeric_limits<decltype(input.mantissa)>::digits - 1),
227 input.mantissa);
228
229 // Divide or multiply, depending on whether log10_low_digit was positive
230 // or negative.
231 fputil::DyadicFloat<DF_BITS> flt_quotient =
232 log10_low_digit > 0 ? fputil::rounded_div(flt_mantissa, power_of_10)
233 : fputil::rounded_mul(flt_mantissa, power_of_10);
234
235 // Convert to an integer.
236 int round_dir;
237 UInt<DF_BITS> integer = flt_quotient.as_mantissa_type_rounded(&round_dir);
238
239 // And take the absolute value.
240 if (flt_quotient.sign.is_neg())
241 integer = -integer;
242
243 // Convert the mantissa integer into a string of decimal digits, and check
244 // to see if it's the right size.
245 const IntegerToString<decltype(integer), radix::Dec> buf{integer};
246 cpp::string_view view = buf.view();
247
248 // Start making the output struct, by copying in the digits from the above
249 // object. At this stage we may also have one digit too many (but that's OK,
250 // there's space for it in the DigitsOutput buffer).
251 DigitsOutput output;
252 output.ndigits = view.size();
253 __builtin_memcpy(output.digits, view.data(), output.ndigits);
254
255 // Set up the output exponent, which is done differently depending on mode.
256 // Also, figure out whether we have one digit too many, and if so, set the
257 // `need_reround` flag and adjust the exponent appropriately.
258 bool need_reround = false;
259 if (e_mode) {
260 // In E mode, the output exponent is the exponent of the first decimal
261 // digit, which we already calculated.
262 output.exponent = log10_input_min;
263
264 // In E mode, we're returning a fixed number of digits, given by
265 // `precision`, so if we have more than that, then we must shorten the
266 // buffer by one digit.
267 //
268 // If this happens, it's because the actual log10 of the input is
269 // log10_input_min + 1. Equivalently, we guessed we'd see something like
270 // X.YZe+NN and instead got WX.YZe+NN. So when we shorten the digit string
271 // by one, we'll also need to increment the output exponent.
272 if (output.ndigits > size_t(precision)) {
273 LIBC_ASSERT(output.ndigits == size_t(precision) + 1);
274 need_reround = true;
275 output.exponent++;
276 }
277 } else {
278 // In F mode, the output exponent is based on the place value of the _last_
279 // digit, so we must recover the exponent of the first digit by adding
280 // the number of digits.
281 //
282 // Because this takes the length of the buffer into account, it sets the
283 // correct decimal exponent even if this digit string is one too long. So
284 // we don't need to adjust the exponent if we reround.
285 output.exponent = int(output.ndigits) - precision - 1;
286
287 // In F mode, the number of returned digits isn't based on `precision`:
288 // it's variable, and we don't mind how many digits we get as long as it
289 // isn't beyond the limit MAX_DIGITS. If it is, we expect that it's only
290 // one digit too long, or else we'd have spotted the problem in advance and
291 // flipped into E mode already.
292 if (output.ndigits > MAX_DIGITS) {
293 LIBC_ASSERT(output.ndigits == MAX_DIGITS + 1);
294 need_reround = true;
295 }
296 }
297
298 if (need_reround) {
299 // If either of the branches above decided that we had one digit too many,
300 // we must now shorten the digit buffer by one. But we can't just truncate:
301 // we need to make sure the remaining n-1 digits are correctly rounded, as
302 // if we'd rounded just once from the original `flt_quotient`.
303 //
304 // In directed rounding modes this can't go wrong. If you had a real number
305 // x, and the first rounding produced floor(x), then the second rounding
306 // wants floor(x/10), and it doesn't matter if you actually compute
307 // floor(floor(x)/10): the result is the same, because each rounding
308 // boundary in the second rounding aligns with one in the first rounding,
309 // which nothing could have crossed. Similarly for rounding away from zero,
310 // with 'floor' replaced with 'ceil' throughout.
311 //
312 // In rounding to nearest, the danger is in the boundary case where the
313 // final digit of the original output is 5. Then if we just rerounded the
314 // digit string to remove the last digit, it would look like an exact
315 // halfway case, and we'd break the tie by choosing the even one of the two
316 // outputs. But if the original value before the first rounding was on one
317 // side or the other of 5, then that supersedes the 'round to even' tie
318 // break. So we need to consult `round_dir` from above, which tells us
319 // which way (if either) the value was adjusted during the first rounding.
320 // Effectively, we treat the last digit as 5+ε or 5-ε.
321 //
322 // To make this work in both directed modes and round-to-nearest mode
323 // without having to look up the rounding direction, a simple rule is: take
324 // account of round_dir if and only if the round digit (the one we're
325 // removing when shortening the buffer) is 5. In directed rounding modes
326 // this makes no difference.
327
328 // Extract the two relevant digits. round_digit is the one we're removing;
329 // new_low_digit is the last one we're keeping, so we need to know if it's
330 // even or odd to handle exact tie cases (when round_dir == 0).
331 --output.ndigits;
332 int round_digit = internal::b36_char_to_int(output.digits[output.ndigits]);
333 int new_low_digit =
334 output.ndigits == 0
335 ? 0
336 : internal::b36_char_to_int(output.digits[output.ndigits - 1]);
337
338 // Make a binary number that we can pass to `fputil::rounding_direction`.
339 // We put new_low_digit at bit 8, and imagine that we're rounding away the
340 // bottom 8 bits. Therefore round_digit must be "just below" bit 8, in the
341 // sense that we set the bottom 8 bits to (256/10 * round_digit) so that
342 // round_digit==5 corresponds to the binary half-way case of 0x80.
343 //
344 // Then we adjust by +1 or -1 based on round_dir if the round digit is 5,
345 // as described above.
346 //
347 // The subexpression `(round_digit * 0x19a) >> 4` is computing the
348 // expression (256/10 * round_digit) mentioned above, accurately enough to
349 // map 5 to exactly 128 but avoiding an integer division (for platforms
350 // where it's slow, e.g. not in hardware).
351 LIBC_NAMESPACE::UInt<64> round_word = (new_low_digit * 256) +
352 ((round_digit * 0x19a) >> 4) +
353 (round_digit == 5 ? -round_dir : 0);
354
355 // Now we can call the existing binary rounding helper function, which
356 // takes account of the rounding mode.
357 if (fputil::rounding_direction(round_word, 8, flt_quotient.sign) > 0) {
358 // If that returned a positive answer, we must round the number up.
359 //
360 // The number is already in decimal, so we need to increment it one digit
361 // at a time. (A bit painful, but better than going back to the integer
362 // we made it from and doing the decimal conversion all over again.)
363 for (size_t i = output.ndigits; i-- > 0;) {
364 if (output.digits[i] != '9') {
365 output.digits[i] = static_cast<char>(internal::int_to_b36_char(
366 internal::b36_char_to_int(output.digits[i]) + 1));
367 break;
368 } else {
369 output.digits[i] = '0';
370 }
371 }
372 }
373 }
374
375 return output;
376}
377
378template <WriteMode write_mode>
379LIBC_INLINE int
380convert_float_inner(Writer<write_mode> *writer, const FormatSection &to_conv,
381 int32_t fraction_len, int exponent, StorageType mantissa,
382 Sign sign, ConversionType ctype) {
383 // If to_conv doesn't specify a precision, the precision defaults to 6.
384 unsigned precision = to_conv.precision < 0 ? 6 : to_conv.precision;
385
386 // Decide if we're displaying a sign character, depending on the format flags
387 // and whether the input is negative.
388 char sign_char = 0;
389 if (sign.is_neg())
390 sign_char = '-';
391 else if ((to_conv.flags & FormatFlags::FORCE_SIGN) == FormatFlags::FORCE_SIGN)
392 sign_char = '+'; // FORCE_SIGN has precedence over SPACE_PREFIX
393 else if ((to_conv.flags & FormatFlags::SPACE_PREFIX) ==
394 FormatFlags::SPACE_PREFIX)
395 sign_char = ' ';
396
397 // Prepare the input to decimal_digits().
398 DigitsInput input(fraction_len, mantissa, exponent, sign);
399
400 // Call decimal_digits() in a different way, based on whether the format
401 // character is 'e', 'f', or 'g'. After this loop we expect to have filled
402 // in the following variables:
403
404 // The decimal digits, and the exponent of the topmost one.
405 DigitsOutput output;
406 // The start and end of the digit string we're displaying, as indices into
407 // `output.digits`. The indices may be out of bounds in either direction, in
408 // which case digits beyond the bounds of the buffer should be displayed as
409 // zeroes.
410 //
411 // As usual, the index 'start' is included, and 'limit' is not.
412 int start, limit;
413 // The index of the digit that we display a decimal point immediately after.
414 // Again, represented as an index in `output.digits`, and may be out of
415 // bounds.
416 int pointpos;
417 // Whether we need to display an "e+NNN" exponent suffix at all.
418 bool show_exponent;
419
420 switch (ctype) {
421 case ConversionType::E:
422 // In E mode, we display one digit more than the specified precision
423 // (`%.6e` means six digits _after_ the decimal point, like 1.123456e+00).
424 //
425 // Also, bound the number of digits we request at MAX_DIGITS.
426 output = decimal_digits(input, cpp::min(precision + 1, MAX_DIGITS), true);
427
428 // We display digits from the start of the buffer, and always output
429 // `precision+1` of them (which will append zeroes if the user requested
430 // more than MAX_DIGITS).
431 start = 0;
432 limit = precision + 1;
433
434 // The decimal point is always after the first digit of the buffer.
435 pointpos = start;
436
437 // The exponent is always displayed explicitly.
438 show_exponent = true;
439 break;
440 case ConversionType::F:
441 // In F mode, we provide decimal_digits() with the unmodified input
442 // precision, and let it give us as many digits as we can.
443 output = decimal_digits(input, precision, false);
444
445 // Initialize (start, limit) to display everything from the first nonzero
446 // digit (necessarily at the start of the output buffer) to the digit at
447 // the correct distance after the decimal point.
448 start = 0;
449 limit = 1 + output.exponent + precision;
450
451 // But we must display at least one digit _before_ the decimal point, i.e.
452 // at least precision+1 digits in total. So if we're not already doing
453 // that, we must correct those values.
454 if (limit <= int(precision))
455 start -= precision + 1 - limit;
456
457 // The decimal point appears precisely 'precision' digits before the end of
458 // the digits we output.
459 pointpos = limit - 1 - precision;
460
461 // The exponent is never displayed.
462 show_exponent = false;
463 break;
464 case ConversionType::G:
465 // In G mode, the precision says exactly how many significant digits you
466 // want. (In that respect it's subtly unlike E mode: %.6g means six digits
467 // _including_ the one before the point, whereas %.6e means six digits
468 // _excluding_ that one.)
469 //
470 // Also, a precision of 0 is treated the same as 1.
471 precision = cpp::max(precision, 1u);
472 output = decimal_digits(input, cpp::min(precision, MAX_DIGITS), true);
473
474 // As in E mode, we default to displaying precisely the digits in the
475 // output buffer.
476 start = 0;
477 limit = precision;
478
479 // If we're not in ALTERNATE_FORM mode, trailing zeroes on the mantissa are
480 // removed (although not to the extent of leaving no digits at all - if the
481 // entire output mantissa is all 0 then we keep a single zero digit).
482 if (!(to_conv.flags & FormatFlags::ALTERNATE_FORM)) {
483 // Start by removing trailing zeroes that were outside the buffer
484 // entirely.
485 limit = cpp::min(limit, int(output.ndigits));
486
487 // Then check the digits in the buffer and remove as many as possible.
488 while (limit > 1 && output.digits[limit - 1] == '0')
489 limit--;
490 }
491
492 // Decide whether to display in %e style with an explicit exponent, or %f
493 // style with the decimal point after the units place.
494 //
495 // %e mode is used to avoid an excessive number of leading zeroes after the
496 // decimal point but before the first nonzero digit (specifically, 0.0001
497 // is fine as it is, but 0.00001 prints as 1e-5), and also to avoid adding
498 // trailing zeroes if the last digit in the buffer is still higher than the
499 // units place.
500 //
501 // output.exponent is an int whereas precision is unsigned, so we must
502 // check output.exponent >= 0 before comparing it against precision to
503 // prevent a negative exponent from wrapping round to a large unsigned int.
504 if ((output.exponent >= 0 && output.exponent >= int(precision)) ||
505 output.exponent < -4) {
506 // Display in %e style, so the point goes after the first digit and the
507 // exponent is shown.
508 pointpos = start;
509 show_exponent = true;
510 } else {
511 // Display in %f style, so the point goes at its true mathematical
512 // location and the exponent is not shown.
513 pointpos = output.exponent;
514 show_exponent = false;
515
516 if (output.exponent < 0) {
517 // If the first digit is below the decimal point, add leading zeroes.
518 // (This _decreases_ start, because output.exponent is negative here.)
519 start += output.exponent;
520 } else if (limit <= output.exponent) {
521 // If the last digit is above the decimal point, add trailing zeroes.
522 // (This may involve putting back some zeroes that we trimmed in the
523 // loop above!)
524 limit = output.exponent + 1;
525 }
526 }
527 break;
528 }
529
530 // Find out for sure whether we're displaying the decimal point, so that we
531 // can include it in the calculation of the total string length for padding.
532 //
533 // We never expect pointpos to be _before_ the start of the displayed range
534 // of digits. (If it had been, we'd have added leading zeroes.) But it might
535 // be beyond the end.
536 //
537 // We don't display the point if it appears immediately after the _last_
538 // digit we display, except in ALTERNATE_FORM mode.
539 int last_point_digit =
540 (to_conv.flags & FormatFlags::ALTERNATE_FORM) ? limit - 1 : limit - 2;
541 bool show_point = pointpos <= last_point_digit;
542
543 // Format the exponent suffix (e+NN, e-NN) into a buffer, or leave the buffer
544 // empty if we're not displaying one.
545 char expbuf[16]; // more than enough space for e+NNNN
546 size_t explen = 0;
547 if (show_exponent) {
548 const IntegerToString<decltype(output.exponent),
549 radix::Dec::WithWidth<2>::WithSign>
550 expcvt{output.exponent};
551 cpp::string_view expview = expcvt.view();
552 expbuf[0] = internal::islower(to_conv.conv_name) ? 'e' : 'E';
553 explen = expview.size() + 1;
554 __builtin_memcpy(expbuf + 1, expview.data(), expview.size());
555 }
556
557 // Now we know enough to work out the length of the unpadded output:
558 // * whether to write a sign
559 // * how many mantissa digits to write
560 // * whether to write a decimal point
561 // * the length of the trailing exponent string.
562 size_t unpadded_len =
563 (sign_char != 0) + (limit - start) + show_point + explen;
564
565 // Work out how much padding is needed.
566 size_t min_width = to_conv.min_width > 0 ? to_conv.min_width : 0;
567 size_t padding_amount = cpp::max(min_width, unpadded_len) - unpadded_len;
568
569 // Work out what the padding looks like and where it appears.
570 enum class Padding {
571 LeadingSpace, // spaces at the start of the string
572 Zero, // zeroes between sign and mantissa
573 TrailingSpace, // spaces at the end of the string
574 } padding = Padding::LeadingSpace;
575 // The '-' flag for left-justification takes priority over the '0' flag
576 if (to_conv.flags & FormatFlags::LEFT_JUSTIFIED)
577 padding = Padding::TrailingSpace;
578 else if (to_conv.flags & FormatFlags::LEADING_ZEROES)
579 padding = Padding::Zero;
580
581 // Finally, write all the output!
582
583 // Leading-space padding, if any
584 if (padding == Padding::LeadingSpace)
585 RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_amount));
586
587 // Sign, if any
588 if (sign_char)
589 RET_IF_RESULT_NEGATIVE(writer->write(sign_char));
590
591 // Zero padding, if any
592 if (padding == Padding::Zero)
593 RET_IF_RESULT_NEGATIVE(writer->write('0', padding_amount));
594
595 // Mantissa digits, maybe with a decimal point
596 for (int pos = start; pos < limit; ++pos) {
597 if (pos >= 0 && pos < int(output.ndigits)) {
598 // Fetch a digit from the buffer
599 RET_IF_RESULT_NEGATIVE(writer->write(output.digits[pos]));
600 } else {
601 // This digit is outside the buffer, so write a zero
602 RET_IF_RESULT_NEGATIVE(writer->write('0'));
603 }
604
605 // Show the decimal point, if this is the digit it comes after
606 if (show_point && pos == pointpos)
607 RET_IF_RESULT_NEGATIVE(writer->write(DECIMAL_POINT));
608 }
609
610 // Exponent
611 RET_IF_RESULT_NEGATIVE(writer->write(cpp::string_view(expbuf, explen)));
612
613 // Trailing-space padding, if any
614 if (padding == Padding::TrailingSpace)
615 RET_IF_RESULT_NEGATIVE(writer->write(' ', padding_amount));
616
617 return WRITE_OK;
618}
619
620template <typename T, WriteMode write_mode,
621 cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
622LIBC_INLINE int
623convert_float_typed(Writer<write_mode> *writer, const FormatSection &to_conv,
624 fputil::FPBits<T> float_bits, ConversionType ctype) {
625 return convert_float_inner(writer, to_conv, float_bits.FRACTION_LEN,
626 float_bits.get_explicit_exponent(),
627 float_bits.get_explicit_mantissa(),
628 float_bits.sign(), ctype);
629}
630
631template <WriteMode write_mode>
632LIBC_INLINE int convert_float_outer(Writer<write_mode> *writer,
633 const FormatSection &to_conv,
634 ConversionType ctype) {
635 if (to_conv.length_modifier == LengthModifier::L) {
636 fputil::FPBits<long double>::StorageType float_raw = to_conv.conv_val_raw;
637 fputil::FPBits<long double> float_bits(float_raw);
638 if (!float_bits.is_inf_or_nan()) {
639 return convert_float_typed<long double>(writer, to_conv, float_bits,
640 ctype);
641 }
642 } else {
643 fputil::FPBits<double>::StorageType float_raw =
644 static_cast<fputil::FPBits<double>::StorageType>(to_conv.conv_val_raw);
645 fputil::FPBits<double> float_bits(float_raw);
646 if (!float_bits.is_inf_or_nan()) {
647 return convert_float_typed<double>(writer, to_conv, float_bits, ctype);
648 }
649 }
650
651 return convert_inf_nan(writer, to_conv);
652}
653
654template <typename T, WriteMode write_mode,
655 cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
656LIBC_INLINE int convert_float_decimal_typed(Writer<write_mode> *writer,
657 const FormatSection &to_conv,
658 fputil::FPBits<T> float_bits) {
659 return convert_float_typed<T>(writer, to_conv, float_bits, ConversionType::F);
660}
661
662template <typename T, WriteMode write_mode,
663 cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
664LIBC_INLINE int convert_float_dec_exp_typed(Writer<write_mode> *writer,
665 const FormatSection &to_conv,
666 fputil::FPBits<T> float_bits) {
667 return convert_float_typed<T>(writer, to_conv, float_bits, ConversionType::E);
668}
669
670template <typename T, WriteMode write_mode,
671 cpp::enable_if_t<cpp::is_floating_point_v<T>, int> = 0>
672LIBC_INLINE int convert_float_dec_auto_typed(Writer<write_mode> *writer,
673 const FormatSection &to_conv,
674 fputil::FPBits<T> float_bits) {
675 return convert_float_typed<T>(writer, to_conv, float_bits, ConversionType::G);
676}
677
678template <WriteMode write_mode>
679LIBC_INLINE int convert_float_decimal(Writer<write_mode> *writer,
680 const FormatSection &to_conv) {
681 return convert_float_outer(writer, to_conv, ConversionType::F);
682}
683
684template <WriteMode write_mode>
685LIBC_INLINE int convert_float_dec_exp(Writer<write_mode> *writer,
686 const FormatSection &to_conv) {
687 return convert_float_outer(writer, to_conv, ConversionType::E);
688}
689
690template <WriteMode write_mode>
691LIBC_INLINE int convert_float_dec_auto(Writer<write_mode> *writer,
692 const FormatSection &to_conv) {
693 return convert_float_outer(writer, to_conv, ConversionType::G);
694}
695
696} // namespace printf_core
697} // namespace LIBC_NAMESPACE_DECL
698
699#endif // LLVM_LIBC_SRC_STDIO_PRINTF_CORE_FLOAT_DEC_CONVERTER_LIMITED_H
700

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of libc/src/stdio/printf_core/float_dec_converter_limited.h