//===-- Utilities to convert floating point values to string ----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLVM_LIBC_SRC___SUPPORT_FLOAT_TO_STRING_H #define LLVM_LIBC_SRC___SUPPORT_FLOAT_TO_STRING_H #include <stdint.h> #include "src/__support/CPP/limits.h" #include "src/__support/CPP/type_traits.h" #include "src/__support/FPUtil/FPBits.h" #include "src/__support/FPUtil/dyadic_float.h" #include "src/__support/big_int.h" #include "src/__support/common.h" #include "src/__support/libc_assert.h" #include "src/__support/macros/attributes.h" #include "src/__support/macros/config.h" // This file has 5 compile-time flags to allow the user to configure the float // to string behavior. These were used to explore tradeoffs during the design // phase, and can still be used to gain specific properties. Unless you // specifically know what you're doing, you should leave all these flags off. // LIBC_COPT_FLOAT_TO_STR_NO_SPECIALIZE_LD // This flag disables the separate long double conversion implementation. It is // not based on the Ryu algorithm, instead generating the digits by // multiplying/dividing the written-out number by 10^9 to get blocks. It's // significantly faster than INT_CALC, only about 10x slower than MEGA_TABLE, // and is small in binary size. Its downside is that it always calculates all // of the digits above the decimal point, making it inefficient for %e calls // with large exponents. This specialization overrides other flags, so this // flag must be set for other flags to effect the long double behavior. // LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE // The Mega Table is ~5 megabytes when compiled. It lists the constants needed // to perform the Ryu Printf algorithm (described below) for all long double // values. This makes it extremely fast for both doubles and long doubles, in // exchange for large binary size. // LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT // Dyadic floats are software floating point numbers, and their accuracy can be // as high as necessary. This option uses 256 bit dyadic floats to calculate // the table values that Ryu Printf needs. This is reasonably fast and very // small compared to the Mega Table, but the 256 bit floats only give accurate // results for the first ~50 digits of the output. In practice this shouldn't // be a problem since long doubles are only accurate for ~35 digits, but the // trailing values all being 0s may cause brittle tests to fail. // LIBC_COPT_FLOAT_TO_STR_USE_INT_CALC // Integer Calculation uses wide integers to do the calculations for the Ryu // Printf table, which is just as accurate as the Mega Table without requiring // as much code size. These integers can be very large (~32KB at max, though // always on the stack) to handle the edges of the long double range. They are // also very slow, taking multiple seconds on a powerful CPU to calculate the // values at the end of the range. If no flag is set, this is used for long // doubles, the flag only changes the double behavior. // LIBC_COPT_FLOAT_TO_STR_NO_TABLE // This flag doesn't change the actual calculation method, instead it is used // to disable the normal Ryu Printf table for configurations that don't use any // table at all. // Default Config: // If no flags are set, doubles use the normal (and much more reasonably sized) // Ryu Printf table and long doubles use their specialized implementation. This // provides good performance and binary size. #ifdef LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE #include "src/__support/ryu_long_double_constants.h" #elif !defined(LIBC_COPT_FLOAT_TO_STR_NO_TABLE) #include "src/__support/ryu_constants.h" #else constexpr size_t IDX_SIZE = 1; constexpr size_t MID_INT_SIZE = 192; #endif // This implementation is based on the Ryu Printf algorithm by Ulf Adams: // Ulf Adams. 2019. Ryƫ revisited: printf floating point conversion. // Proc. ACM Program. Lang. 3, OOPSLA, Article 169 (October 2019), 23 pages. // https://doi.org/10.1145/3360595 // This version is modified to require significantly less memory (it doesn't use // a large buffer to store the result). // The general concept of this algorithm is as follows: // We want to calculate a 9 digit segment of a floating point number using this // formula: floor((mantissa * 2^exponent)/10^i) % 10^9. // To do so normally would involve large integers (~1000 bits for doubles), so // we use a shortcut. We can avoid calculating 2^exponent / 10^i by using a // lookup table. The resulting intermediate value needs to be about 192 bits to // store the result with enough precision. Since this is all being done with // integers for appropriate precision, we would run into a problem if // i > exponent since then 2^exponent / 10^i would be less than 1. To correct // for this, the actual calculation done is 2^(exponent + c) / 10^i, and then // when multiplying by the mantissa we reverse this by dividing by 2^c, like so: // floor((mantissa * table[exponent][i])/(2^c)) % 10^9. // This gives a 9 digit value, which is small enough to fit in a 32 bit integer, // and that integer is converted into a string as normal, and called a block. In // this implementation, the most recent block is buffered, so that if rounding // is necessary the block can be adjusted before being written to the output. // Any block that is all 9s adds one to the max block counter and doesn't clear // the buffer because they can cause the block above them to be rounded up. __llvm_libc_20_0_0_git // namespace LIBC_NAMESPACE_DECL #endif // LLVM_LIBC_SRC___SUPPORT_FLOAT_TO_STRING_H