diff --git a/libc/config/config.json b/libc/config/config.json index 77d10d75f3646..6a208cc556611 100644 --- a/libc/config/config.json +++ b/libc/config/config.json @@ -13,7 +13,7 @@ "doc": "Disable handling of %n in printf format string." }, "LIBC_CONF_PRINTF_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE": { - "value": true, + "value": false, "doc": "Use large table for better printf long double performance." } }, diff --git a/libc/docs/dev/printf_behavior.rst b/libc/docs/dev/printf_behavior.rst index 29b1b17ebaecb..bc60aa43ee2b6 100644 --- a/libc/docs/dev/printf_behavior.rst +++ b/libc/docs/dev/printf_behavior.rst @@ -13,7 +13,7 @@ C standard and POSIX standard. If any behavior is not mentioned here, it should be assumed to follow the behavior described in those standards. The LLVM-libc codebase is under active development, and may change. This -document was last updated [August 18, 2023] by [michaelrj] and may +document was last updated [January 8, 2024] by [michaelrj] and may not be accurate after this point. The behavior of LLVM-libc's printf is heavily influenced by compile-time flags. @@ -87,14 +87,26 @@ are not recommended to be adjusted except by persons familiar with the Printf Ryu Algorithm. Additionally they have no effect when float conversions are disabled. +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 slightly inefficient for %e +calls with large exponents. This is the default. 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 ------------------------------------------------- When set, the float to string decimal conversion algorithm will use a larger table to accelerate long double conversions. This larger table is around 5MB of -size when compiled. This flag is enabled by default in the CMake. +size when compiled. -LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT(_LD) --------------------------------------------- +LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT +--------------------------------------- When set, the float to string decimal conversion algorithm will use dyadic floats instead of a table when performing floating point conversions. This results in ~50 digits of accuracy in the result, then zeroes for the remaining @@ -107,8 +119,7 @@ LIBC_COPT_FLOAT_TO_STR_USE_INT_CALC When set, the float to string decimal conversion algorithm will use wide integers instead of a table when performing floating point conversions. This gives the same results as the table, but is very slow at the extreme ends of -the long double range. If no flags are set this is the default behavior for -long double conversions. +the long double range. LIBC_COPT_FLOAT_TO_STR_NO_TABLE ------------------------------- diff --git a/libc/src/__support/UInt.h b/libc/src/__support/UInt.h index 947b23588fcdf..7726b6d88f0d2 100644 --- a/libc/src/__support/UInt.h +++ b/libc/src/__support/UInt.h @@ -27,10 +27,17 @@ namespace LIBC_NAMESPACE::cpp { template struct BigInt { + // This being hardcoded as 64 is okay because we're using uint64_t as our + // internal type which will always be 64 bits. + using word_type = uint64_t; + LIBC_INLINE_VAR static constexpr size_t WORD_SIZE = + sizeof(word_type) * CHAR_BIT; + + // TODO: Replace references to 64 with WORD_SIZE, and uint64_t with word_type. static_assert(Bits > 0 && Bits % 64 == 0, "Number of bits in BigInt should be a multiple of 64."); LIBC_INLINE_VAR static constexpr size_t WORDCOUNT = Bits / 64; - cpp::array val{}; + cpp::array val{}; LIBC_INLINE_VAR static constexpr uint64_t MASK32 = 0xFFFFFFFFu; @@ -448,6 +455,8 @@ template struct BigInt { // pos is the index of the current 64-bit chunk that we are processing. size_t pos = WORDCOUNT; + // TODO: look into if constexpr(Bits > 256) skip leading zeroes. + for (size_t q_pos = WORDCOUNT - lower_pos; q_pos > 0; --q_pos) { // q_pos is 1 + the index of the current 64-bit chunk of the quotient // being processed. diff --git a/libc/src/__support/float_to_string.h b/libc/src/__support/float_to_string.h index ab1afbe54dfac..4dc9d6eb3cb73 100644 --- a/libc/src/__support/float_to_string.h +++ b/libc/src/__support/float_to_string.h @@ -11,20 +11,29 @@ #include +#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/UInt.h" #include "src/__support/common.h" #include "src/__support/libc_assert.h" +#include "src/__support/macros/attributes.h" // This file has 5 compile-time flags to allow the user to configure the float -// to string behavior. These allow the user to select which 2 of the 3 useful -// properties they want. The useful properties are: -// 1) Speed of Evaluation -// 2) Small Size of Binary -// 3) Centered Output Value -// These are explained below with the flags that are missing each one. +// 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 @@ -33,16 +42,13 @@ // exchange for large binary size. // LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT -// LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT_LD // 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. The _LD -// version of this flag only effects the long double calculations, and the -// other version effects both long double and double. +// 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 @@ -60,9 +66,8 @@ // Default Config: // If no flags are set, doubles use the normal (and much more reasonably sized) -// Ryu Printf table and long doubles use Integer Calculation. This is because -// long doubles are rarely used and the normal Ryu Printf table is very fast -// for doubles. +// 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" @@ -104,6 +109,8 @@ namespace LIBC_NAMESPACE { using BlockInt = uint32_t; constexpr uint32_t BLOCK_SIZE = 9; +constexpr uint64_t EXP5_9 = 1953125; +constexpr uint64_t EXP10_9 = 1000000000; using FPBits = fputil::FPBits; @@ -114,7 +121,7 @@ constexpr size_t CALC_SHIFT_CONST = 128; namespace internal { // Returns floor(log_10(2^e)); requires 0 <= e <= 42039. -LIBC_INLINE constexpr uint32_t log10_pow2(const uint64_t e) { +LIBC_INLINE constexpr uint32_t log10_pow2(uint64_t e) { LIBC_ASSERT(e <= 42039 && "Incorrect exponent to perform log10_pow2 approximation."); // This approximation is based on the float value for log_10(2). It first @@ -140,7 +147,7 @@ LIBC_INLINE constexpr uint32_t log10_pow2(const uint64_t e) { } // Same as above, but with different constants. -LIBC_INLINE constexpr uint32_t log2_pow5(const uint64_t e) { +LIBC_INLINE constexpr uint32_t log2_pow5(uint64_t e) { return static_cast((e * 0x12934f0979bll) >> 39); } @@ -148,19 +155,20 @@ LIBC_INLINE constexpr uint32_t log2_pow5(const uint64_t e) { // power of 2 was also a power of 10, but since that doesn't exist this is // always accurate. This is used to calculate the maximum number of base-10 // digits a given e-bit number could have. -LIBC_INLINE constexpr uint32_t ceil_log10_pow2(const uint32_t e) { +LIBC_INLINE constexpr uint32_t ceil_log10_pow2(uint32_t e) { return log10_pow2(e) + 1; } +LIBC_INLINE constexpr uint32_t div_ceil(uint32_t num, uint32_t denom) { + return (num + (denom - 1)) / denom; +} + // Returns the maximum number of 9 digit blocks a number described by the given // index (which is ceil(exponent/16)) and mantissa width could need. -LIBC_INLINE constexpr uint32_t length_for_num(const uint32_t idx, - const uint32_t mantissa_width) { - //+8 to round up when dividing by 9 - return (ceil_log10_pow2(idx) + ceil_log10_pow2(mantissa_width + 1) + - (BLOCK_SIZE - 1)) / - BLOCK_SIZE; - // return (ceil_log10_pow2(16 * idx + mantissa_width) + 8) / 9; +LIBC_INLINE constexpr uint32_t length_for_num(uint32_t idx, + uint32_t mantissa_width) { + return div_ceil(ceil_log10_pow2(idx) + ceil_log10_pow2(mantissa_width + 1), + BLOCK_SIZE); } // The formula for the table when i is positive (or zero) is as follows: @@ -188,24 +196,21 @@ LIBC_INLINE constexpr cpp::UInt get_table_positive(int exponent, // can get, since it needs to be small enough to fit in the result UInt, // otherwise we'll get truncation on return. constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(1000000000) + (cpp::UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); - constexpr uint64_t FIVE_EXP_NINE = 1953125; - num = cpp::UInt(1) << (shift_amount); if (i > 0) { - cpp::UInt fives(FIVE_EXP_NINE); + cpp::UInt fives(EXP5_9); fives.pow_n(i); num = num / fives; } num = num + 1; if (num > MOD_SIZE) { - auto rem = - num.div_uint32_times_pow_2( - 1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)) - .value(); + auto rem = num.div_uint32_times_pow_2( + EXP10_9, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)) + .value(); num = rem; } return num; @@ -229,7 +234,7 @@ LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, } fputil::DyadicFloat num(false, 0, 1); constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(1000000000) + (cpp::UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); constexpr cpp::UInt FIVE_EXP_MINUS_NINE_MANT{ @@ -250,8 +255,8 @@ LIBC_INLINE cpp::UInt get_table_positive_df(int exponent, if (int_num > MOD_SIZE) { auto rem = int_num - .div_uint32_times_pow_2( - 1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)) + .div_uint32_times_pow_2(EXP10_9, CALC_SHIFT_CONST + + (IDX_SIZE > 1 ? IDX_SIZE : 0)) .value(); int_num = rem; } @@ -274,11 +279,9 @@ LIBC_INLINE cpp::UInt get_table_negative(int exponent, size_t i) { int shift_amount = CALC_SHIFT_CONST - exponent; cpp::UInt num(1); constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(1000000000) + (cpp::UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); - constexpr uint64_t TEN_EXP_NINE = 1000000000; - constexpr uint64_t FIVE_EXP_NINE = 1953125; size_t ten_blocks = i; size_t five_blocks = 0; if (shift_amount < 0) { @@ -295,12 +298,12 @@ LIBC_INLINE cpp::UInt get_table_negative(int exponent, size_t i) { } if (five_blocks > 0) { - cpp::UInt fives(FIVE_EXP_NINE); + cpp::UInt fives(EXP5_9); fives.pow_n(five_blocks); num = fives; } if (ten_blocks > 0) { - cpp::UInt tens(TEN_EXP_NINE); + cpp::UInt tens(EXP10_9); tens.pow_n(ten_blocks); if (five_blocks <= 0) { num = tens; @@ -315,10 +318,9 @@ LIBC_INLINE cpp::UInt get_table_negative(int exponent, size_t i) { num = num >> (-shift_amount); } if (num > MOD_SIZE) { - auto rem = - num.div_uint32_times_pow_2( - 1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)) - .value(); + auto rem = num.div_uint32_times_pow_2( + EXP10_9, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)) + .value(); num = rem; } return num; @@ -340,10 +342,10 @@ LIBC_INLINE cpp::UInt get_table_negative_df(int exponent, fputil::DyadicFloat num(false, 0, 1); constexpr cpp::UInt MOD_SIZE = - (cpp::UInt(1000000000) + (cpp::UInt(EXP10_9) << (CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0))); - constexpr cpp::UInt TEN_EXP_NINE_MANT(1000000000); + constexpr cpp::UInt TEN_EXP_NINE_MANT(EXP10_9); static const fputil::DyadicFloat TEN_EXP_NINE(false, 0, TEN_EXP_NINE_MANT); @@ -358,8 +360,8 @@ LIBC_INLINE cpp::UInt get_table_negative_df(int exponent, if (int_num > MOD_SIZE) { auto rem = int_num - .div_uint32_times_pow_2( - 1000000000, CALC_SHIFT_CONST + (IDX_SIZE > 1 ? IDX_SIZE : 0)) + .div_uint32_times_pow_2(EXP10_9, CALC_SHIFT_CONST + + (IDX_SIZE > 1 ? IDX_SIZE : 0)) .value(); int_num = rem; } @@ -379,7 +381,7 @@ LIBC_INLINE uint32_t fast_uint_mod_1e9(const cpp::UInt &val) { const uint64_t result = static_cast(middle[2]); const uint64_t shifted = result >> 29; return static_cast(static_cast(val) - - (1000000000 * shifted)); + (EXP10_9 * shifted)); } LIBC_INLINE uint32_t mul_shift_mod_1e9(const FPBits::StorageType mantissa, @@ -387,8 +389,7 @@ LIBC_INLINE uint32_t mul_shift_mod_1e9(const FPBits::StorageType mantissa, const int32_t shift_amount) { cpp::UInt val(large); val = (val * mantissa) >> shift_amount; - return static_cast( - val.div_uint32_times_pow_2(1000000000, 0).value()); + return static_cast(val.div_uint32_times_pow_2(EXP10_9, 0).value()); } } // namespace internal @@ -448,6 +449,8 @@ class FloatToString { // shift_amount = -(c0 - exponent) = c_0 + 16 * ceil(exponent/16) - // exponent + const uint32_t pos_exp = idx * IDX_SIZE; + cpp::UInt val; #if defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT) @@ -458,24 +461,25 @@ class FloatToString { // ---------------------------- INT CALC MODE ---------------------------- const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - const uint64_t MAX_POW_2_SIZE = - exponent + CALC_SHIFT_CONST - (BLOCK_SIZE * block_index); + pos_exp + CALC_SHIFT_CONST - (BLOCK_SIZE * block_index); const uint64_t MAX_POW_5_SIZE = internal::log2_pow5(BLOCK_SIZE * block_index); const uint64_t MAX_INT_SIZE = (MAX_POW_2_SIZE > MAX_POW_5_SIZE) ? MAX_POW_2_SIZE : MAX_POW_5_SIZE; if (MAX_INT_SIZE < 1024) { - val = internal::get_table_positive<1024>(IDX_SIZE * idx, block_index); + val = internal::get_table_positive<1024>(pos_exp, block_index); } else if (MAX_INT_SIZE < 2048) { - val = internal::get_table_positive<2048>(IDX_SIZE * idx, block_index); + val = internal::get_table_positive<2048>(pos_exp, block_index); } else if (MAX_INT_SIZE < 4096) { - val = internal::get_table_positive<4096>(IDX_SIZE * idx, block_index); + val = internal::get_table_positive<4096>(pos_exp, block_index); } else if (MAX_INT_SIZE < 8192) { - val = internal::get_table_positive<8192>(IDX_SIZE * idx, block_index); + val = internal::get_table_positive<8192>(pos_exp, block_index); + } else if (MAX_INT_SIZE < 16384) { + val = internal::get_table_positive<16384>(pos_exp, block_index); } else { - val = internal::get_table_positive<16384>(IDX_SIZE * idx, block_index); + val = internal::get_table_positive<16384 + 128>(pos_exp, block_index); } #else // ----------------------------- TABLE MODE ------------------------------ @@ -483,9 +487,9 @@ class FloatToString { val = POW10_SPLIT[POW10_OFFSET[idx] + block_index]; #endif - const uint32_t shift_amount = - SHIFT_CONST + (static_cast(IDX_SIZE) * idx) - exponent; - const uint32_t digits = + const uint32_t shift_amount = SHIFT_CONST + pos_exp - exponent; + + const BlockInt digits = internal::mul_shift_mod_1e9(mantissa, val, (int32_t)(shift_amount)); return digits; } else { @@ -499,35 +503,35 @@ class FloatToString { cpp::UInt val; + const uint32_t pos_exp = idx * IDX_SIZE; + #if defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT) // ----------------------- DYADIC FLOAT CALC MODE ------------------------ const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - val = - internal::get_table_negative_df<256>(idx * IDX_SIZE, block_index + 1); + val = internal::get_table_negative_df<256>(pos_exp, block_index + 1); #elif defined(LIBC_COPT_FLOAT_TO_STR_USE_INT_CALC) // ---------------------------- INT CALC MODE ---------------------------- const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - const uint64_t TEN_BLOCKS = (block_index + 1) * BLOCK_SIZE; - const uint64_t MAX_INT_SIZE = internal::log2_pow5(TEN_BLOCKS); + + const uint64_t NUM_FIVES = (block_index + 1) * BLOCK_SIZE; + // Round MAX_INT_SIZE up to the nearest 64 (adding 1 because log2_pow5 + // implicitly rounds down). + const uint64_t MAX_INT_SIZE = + ((internal::log2_pow5(NUM_FIVES) / 64) + 1) * 64; if (MAX_INT_SIZE < 1024) { - val = - internal::get_table_negative<1024>(idx * IDX_SIZE, block_index + 1); + val = internal::get_table_negative<1024>(pos_exp, block_index + 1); } else if (MAX_INT_SIZE < 2048) { - val = - internal::get_table_negative<2048>(idx * IDX_SIZE, block_index + 1); + val = internal::get_table_negative<2048>(pos_exp, block_index + 1); } else if (MAX_INT_SIZE < 4096) { - val = - internal::get_table_negative<4096>(idx * IDX_SIZE, block_index + 1); + val = internal::get_table_negative<4096>(pos_exp, block_index + 1); } else if (MAX_INT_SIZE < 8192) { - val = - internal::get_table_negative<8192>(idx * IDX_SIZE, block_index + 1); + val = internal::get_table_negative<8192>(pos_exp, block_index + 1); } else if (MAX_INT_SIZE < 16384) { - val = internal::get_table_negative<16384>(idx * IDX_SIZE, - block_index + 1); + val = internal::get_table_negative<16384>(pos_exp, block_index + 1); } else { - val = internal::get_table_negative<32768>(idx * IDX_SIZE, - block_index + 1); + val = internal::get_table_negative<16384 + 8192>(pos_exp, + block_index + 1); } #else // ----------------------------- TABLE MODE ------------------------------ @@ -545,8 +549,8 @@ class FloatToString { val = POW10_SPLIT_2[p]; #endif const int32_t shift_amount = - SHIFT_CONST + (-exponent - (static_cast(IDX_SIZE) * idx)); - uint32_t digits = + SHIFT_CONST + (-exponent - static_cast(pos_exp)); + BlockInt digits = internal::mul_shift_mod_1e9(mantissa, val, shift_amount); return digits; } else { @@ -563,27 +567,29 @@ class FloatToString { } LIBC_INLINE constexpr size_t get_positive_blocks() { - if (exponent >= -FRACTION_LEN) { - const uint32_t idx = - exponent < 0 - ? 0 - : static_cast(exponent + (IDX_SIZE - 1)) / IDX_SIZE; - const uint32_t len = - internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN); - return len; - } else { + if (exponent < -FRACTION_LEN) return 0; - } + const uint32_t idx = + exponent < 0 + ? 0 + : static_cast(exponent + (IDX_SIZE - 1)) / IDX_SIZE; + return internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN); } // This takes the index of a block after the decimal point (a negative block) // and return if it's sure that all of the digits after it are zero. - LIBC_INLINE constexpr bool is_lowest_block(size_t block_index) { + LIBC_INLINE constexpr bool is_lowest_block(size_t negative_block_index) { #ifdef LIBC_COPT_FLOAT_TO_STR_NO_TABLE - return false; + // The decimal representation of 2**(-i) will have exactly i digits after + // the decimal point. + int num_requested_digits = + static_cast((negative_block_index + 1) * BLOCK_SIZE); + + return num_requested_digits > -exponent; #else const int32_t idx = -exponent / IDX_SIZE; - const size_t p = POW10_OFFSET_2[idx] + block_index - MIN_BLOCK_2[idx]; + const size_t p = + POW10_OFFSET_2[idx] + negative_block_index - MIN_BLOCK_2[idx]; // If the remaining digits are all 0, then this is the lowest block. return p >= POW10_OFFSET_2[idx + 1]; #endif @@ -591,169 +597,242 @@ class FloatToString { LIBC_INLINE constexpr size_t zero_blocks_after_point() { #ifdef LIBC_COPT_FLOAT_TO_STR_NO_TABLE + if (exponent < -FRACTION_LEN) { + const int pos_exp = -exponent - 1; + const uint32_t pos_idx = + static_cast(pos_exp + (IDX_SIZE - 1)) / IDX_SIZE; + const int32_t pos_len = ((internal::ceil_log10_pow2(pos_idx * IDX_SIZE) - + internal::ceil_log10_pow2(FRACTION_LEN + 1)) / + BLOCK_SIZE) - + 1; + return static_cast(pos_len > 0 ? pos_len : 0); + } return 0; - // TODO (michaelrj): Find a good algorithm for this that doesn't use a - // table. #else return MIN_BLOCK_2[-exponent / IDX_SIZE]; #endif } }; -#ifndef LIBC_LONG_DOUBLE_IS_FLOAT64 +#if !defined(LIBC_LONG_DOUBLE_IS_FLOAT64) && \ + !defined(LIBC_COPT_FLOAT_TO_STR_NO_SPECIALIZE_LD) // --------------------------- LONG DOUBLE FUNCTIONS --------------------------- -template <> -LIBC_INLINE constexpr size_t FloatToString::get_positive_blocks() { - if (exponent >= -FRACTION_LEN) { - const uint32_t idx = - exponent < 0 - ? 0 - : static_cast(exponent + (IDX_SIZE - 1)) / IDX_SIZE; - const uint32_t len = internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN); - return len; - } else { - return 0; +// this algorithm will work exactly the same for 80 bit and 128 bit long +// doubles. They have the same max exponent, but even if they didn't the +// constants should be calculated to be correct for any provided floating point +// type. + +template <> class FloatToString { + fputil::FPBits float_bits; + bool is_negative = 0; + int exponent = 0; + FPBits::StorageType mantissa = 0; + + static constexpr int FRACTION_LEN = fputil::FPBits::FRACTION_LEN; + static constexpr int EXP_BIAS = fputil::FPBits::EXP_BIAS; + static constexpr size_t UINT_WORD_SIZE = 64; + + static constexpr size_t FLOAT_AS_INT_WIDTH = + internal::div_ceil(fputil::FPBits::MAX_BIASED_EXPONENT - + FPBits::EXP_BIAS, + UINT_WORD_SIZE) * + UINT_WORD_SIZE; + static constexpr size_t EXTRA_INT_WIDTH = + internal::div_ceil(sizeof(long double) * CHAR_BIT, UINT_WORD_SIZE) * + UINT_WORD_SIZE; + + using wide_int = cpp::UInt; + + // float_as_fixed represents the floating point number as a fixed point number + // with the point EXTRA_INT_WIDTH bits from the left of the number. This can + // store any number with a negative exponent. + wide_int float_as_fixed = 0; + int int_block_index = 0; + + static constexpr size_t BLOCK_BUFFER_LEN = + internal::div_ceil(internal::log10_pow2(FLOAT_AS_INT_WIDTH), BLOCK_SIZE); + BlockInt block_buffer[BLOCK_BUFFER_LEN] = {0}; + size_t block_buffer_valid = 0; + + template + LIBC_INLINE static constexpr BlockInt grab_digits(cpp::UInt &int_num) { + auto wide_result = int_num.div_uint32_times_pow_2(EXP5_9, 9); + // the optional only comes into effect when dividing by 0, which will + // never happen here. Thus, we just assert that it has value. + LIBC_ASSERT(wide_result.has_value()); + return static_cast(wide_result.value()); } -} -template <> -LIBC_INLINE constexpr size_t -FloatToString::zero_blocks_after_point() { -#ifdef LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE - return MIN_BLOCK_2[-exponent / IDX_SIZE]; -#else - return 0; - // TODO (michaelrj): Find a good algorithm for this that doesn't use a table. -#endif -} + LIBC_INLINE static constexpr void zero_leading_digits(wide_int &int_num) { + // WORD_SIZE is the width of the numbers used to internally represent the + // UInt + for (size_t i = 0; i < EXTRA_INT_WIDTH / wide_int::WORD_SIZE; ++i) + int_num[i + (FLOAT_AS_INT_WIDTH / wide_int::WORD_SIZE)] = 0; + } -template <> -LIBC_INLINE constexpr bool FloatToString::is_lowest_block(size_t) { - return false; -} + // init_convert initializes float_as_int, cur_block, and block_buffer based on + // the mantissa and exponent of the initial number. Calling it will always + // return the class to the starting state. + LIBC_INLINE constexpr void init_convert() { + // No calculation necessary for the 0 case. + if (mantissa == 0 && exponent == 0) + return; + + if (exponent > 0) { + // if the exponent is positive, then the number is fully above the decimal + // point. In this case we represent the float as an integer, then divide + // by 10^BLOCK_SIZE and take the remainder as our next block. This + // generates the digits from right to left, but the digits will be written + // from left to right, so it caches the results so they can be read in + // reverse order. + + wide_int float_as_int = mantissa; + + float_as_int.shift_left(exponent); + int_block_index = 0; + + while (float_as_int > 0) { + block_buffer[int_block_index] = grab_digits(float_as_int); + ++int_block_index; + } + block_buffer_valid = int_block_index; + + } else { + // if the exponent is not positive, then the number is at least partially + // below the decimal point. In this case we represent the float as a fixed + // point number with the decimal point after the top EXTRA_INT_WIDTH bits. + float_as_fixed = mantissa; + + const int SHIFT_AMOUNT = FLOAT_AS_INT_WIDTH + exponent; + static_assert(EXTRA_INT_WIDTH >= sizeof(long double) * 8); + float_as_fixed.shift_left(SHIFT_AMOUNT); + + // If there are still digits above the decimal point, handle those. + if (float_as_fixed.clz() < EXTRA_INT_WIDTH) { + cpp::UInt above_decimal_point = + float_as_fixed >> FLOAT_AS_INT_WIDTH; + + size_t positive_int_block_index = 0; + while (above_decimal_point > 0) { + block_buffer[positive_int_block_index] = + grab_digits(above_decimal_point); + ++positive_int_block_index; + } + block_buffer_valid = positive_int_block_index; + + // Zero all digits above the decimal point. + zero_leading_digits(float_as_fixed); + int_block_index = 0; + } + } + } -template <> -LIBC_INLINE constexpr BlockInt -FloatToString::get_positive_block(int block_index) { - if (exponent >= -FRACTION_LEN) { +public: + LIBC_INLINE constexpr FloatToString(long double init_float) + : float_bits(init_float) { + is_negative = float_bits.is_neg(); + exponent = float_bits.get_explicit_exponent(); + mantissa = float_bits.get_explicit_mantissa(); + + // Adjust for the width of the mantissa. + exponent -= FRACTION_LEN; + + this->init_convert(); + } + + LIBC_INLINE constexpr size_t get_positive_blocks() { + if (exponent < -FRACTION_LEN) + return 0; - // idx is ceil(exponent/16) or 0 if exponent is negative. This is used to - // find the coarse section of the POW10_SPLIT table that will be used to - // calculate the 9 digit window, as well as some other related values. const uint32_t idx = exponent < 0 ? 0 : static_cast(exponent + (IDX_SIZE - 1)) / IDX_SIZE; - const uint32_t pos_exp = idx * IDX_SIZE; - - // shift_amount = -(c0 - exponent) = c_0 + 16 * ceil(exponent/16) - exponent + return internal::length_for_num(idx * IDX_SIZE, FRACTION_LEN); + } - cpp::UInt val; + LIBC_INLINE constexpr size_t zero_blocks_after_point() { #ifdef LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE - // ------------------------------ TABLE MODE ------------------------------- - const int32_t SHIFT_CONST = TABLE_SHIFT_CONST; - val = POW10_SPLIT[POW10_OFFSET[idx] + block_index]; - -#elif defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT) || \ - defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT_LD) - // ------------------------ DYADIC FLOAT CALC MODE ------------------------- - const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - val = internal::get_table_positive_df<256>(pos_exp, block_index); + return MIN_BLOCK_2[-exponent / IDX_SIZE]; #else - // ----------------------------- INT CALC MODE ----------------------------- - const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - const uint64_t MAX_POW_2_SIZE = - pos_exp + CALC_SHIFT_CONST - (BLOCK_SIZE * block_index); - const uint64_t MAX_POW_5_SIZE = - internal::log2_pow5(BLOCK_SIZE * block_index); - const uint64_t MAX_INT_SIZE = - (MAX_POW_2_SIZE > MAX_POW_5_SIZE) ? MAX_POW_2_SIZE : MAX_POW_5_SIZE; - - if (MAX_INT_SIZE < 1024) { - val = internal::get_table_positive<1024>(pos_exp, block_index); - } else if (MAX_INT_SIZE < 2048) { - val = internal::get_table_positive<2048>(pos_exp, block_index); - } else if (MAX_INT_SIZE < 4096) { - val = internal::get_table_positive<4096>(pos_exp, block_index); - } else if (MAX_INT_SIZE < 8192) { - val = internal::get_table_positive<8192>(pos_exp, block_index); - } else if (MAX_INT_SIZE < 16384) { - val = internal::get_table_positive<16384>(pos_exp, block_index); - } else { - val = internal::get_table_positive<16384 + 128>(pos_exp, block_index); - } -#endif - const uint32_t shift_amount = SHIFT_CONST + pos_exp - exponent; + if (exponent >= -FRACTION_LEN) + return 0; - const BlockInt digits = - internal::mul_shift_mod_1e9(mantissa, val, (int32_t)(shift_amount)); - return digits; - } else { - return 0; + const int pos_exp = -exponent - 1; + const uint32_t pos_idx = + static_cast(pos_exp + (IDX_SIZE - 1)) / IDX_SIZE; + const int32_t pos_len = ((internal::ceil_log10_pow2(pos_idx * IDX_SIZE) - + internal::ceil_log10_pow2(FRACTION_LEN + 1)) / + BLOCK_SIZE) - + 1; + return static_cast(pos_len > 0 ? pos_len : 0); +#endif } -} -template <> -LIBC_INLINE constexpr BlockInt -FloatToString::get_negative_block(int block_index) { - if (exponent < 0) { - const int32_t idx = -exponent / IDX_SIZE; + LIBC_INLINE constexpr bool is_lowest_block(size_t negative_block_index) { + // The decimal representation of 2**(-i) will have exactly i digits after + // the decimal point. + const int num_requested_digits = + static_cast((negative_block_index + 1) * BLOCK_SIZE); - cpp::UInt val; -#ifdef LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE - // ------------------------------ TABLE MODE ------------------------------- - const int32_t SHIFT_CONST = TABLE_SHIFT_CONST; + return num_requested_digits > -exponent; + } - // if the requested block is zero - if (block_index < MIN_BLOCK_2[idx]) { + LIBC_INLINE constexpr BlockInt get_positive_block(int block_index) { + if (exponent < -FRACTION_LEN) return 0; - } - const uint32_t p = POW10_OFFSET_2[idx] + block_index - MIN_BLOCK_2[idx]; - // If every digit after the requested block is zero. - if (p >= POW10_OFFSET_2[idx + 1]) { + if (block_index > static_cast(block_buffer_valid) || block_index < 0) return 0; + + return block_buffer[block_index]; + } + + LIBC_INLINE constexpr BlockInt get_negative_block(int negative_block_index) { + if (exponent >= 0) + return 0; + + // negative_block_index starts at 0 with the first block after the decimal + // point, and 1 with the second and so on. This converts to the same + // block_index used everywhere else. + + const int block_index = -1 - negative_block_index; + + // If we're currently after the requested block (remember these are + // negative indices) we reset the number to the start. This is only + // likely to happen in %g calls. This will also reset int_block_index. + // if (block_index > int_block_index) { + // init_convert(); + // } + + // Printf is the only existing user of this code and it will only ever move + // downwards, except for %g but that currently creates a second + // float_to_string object so this assertion still holds. If a new user needs + // the ability to step backwards, uncomment the code above. + LIBC_ASSERT(block_index <= int_block_index); + + // If we are currently before the requested block. Step until we reach the + // requested block. This is likely to only be one step. + while (block_index < int_block_index) { + zero_leading_digits(float_as_fixed); + float_as_fixed.mul(EXP10_9); + --int_block_index; } - val = POW10_SPLIT_2[p]; -#elif defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT) || \ - defined(LIBC_COPT_FLOAT_TO_STR_USE_DYADIC_FLOAT_LD) - // ------------------------ DYADIC FLOAT CALC MODE ------------------------- - const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - - val = internal::get_table_negative_df<256>(idx * IDX_SIZE, block_index + 1); -#else // table mode - // ----------------------------- INT CALC MODE ----------------------------- - const int32_t SHIFT_CONST = CALC_SHIFT_CONST; - - const uint64_t TEN_BLOCKS = (block_index + 1) * BLOCK_SIZE; - const uint64_t MAX_INT_SIZE = internal::log2_pow5(TEN_BLOCKS); - - if (MAX_INT_SIZE < 1024) { - val = internal::get_table_negative<1024>(idx * IDX_SIZE, block_index + 1); - } else if (MAX_INT_SIZE < 2048) { - val = internal::get_table_negative<2048>(idx * IDX_SIZE, block_index + 1); - } else if (MAX_INT_SIZE < 4096) { - val = internal::get_table_negative<4096>(idx * IDX_SIZE, block_index + 1); - } else if (MAX_INT_SIZE < 8192) { - val = internal::get_table_negative<8192>(idx * IDX_SIZE, block_index + 1); - } else if (MAX_INT_SIZE < 16384) { - val = - internal::get_table_negative<16384>(idx * IDX_SIZE, block_index + 1); - } else { - val = internal::get_table_negative<16384 + 8192>(idx * IDX_SIZE, - block_index + 1); - } -#endif - const int32_t shift_amount = - SHIFT_CONST + (-exponent - static_cast(IDX_SIZE * idx)); - BlockInt digits = internal::mul_shift_mod_1e9(mantissa, val, shift_amount); - return digits; - } else { - return 0; + + // We're now on the requested block, return the current block. + return static_cast(float_as_fixed >> FLOAT_AS_INT_WIDTH); } -} -#endif // LIBC_LONG_DOUBLE_IS_FLOAT64 + LIBC_INLINE constexpr BlockInt get_block(int block_index) { + if (block_index >= 0) + return get_positive_block(block_index); + + return get_negative_block(-1 - block_index); + } +}; + +#endif // !LIBC_LONG_DOUBLE_IS_FLOAT64 && + // !LIBC_COPT_FLOAT_TO_STR_NO_SPECIALIZE_LD } // namespace LIBC_NAMESPACE diff --git a/libc/test/src/stdio/sprintf_test.cpp b/libc/test/src/stdio/sprintf_test.cpp index b22378b22ab12..07501ac751fa3 100644 --- a/libc/test/src/stdio/sprintf_test.cpp +++ b/libc/test/src/stdio/sprintf_test.cpp @@ -1036,196 +1036,119 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) { ASSERT_STREQ_LEN(written, buff, "-NAN"); #endif - // Length Modifier Tests. + // Min Width Tests. - // TODO(michaelrj): Add tests for LIBC_LONG_DOUBLE_IS_FLOAT64 and 128 bit long - // double systems. - // TODO(michaelrj): Fix the tests to only depend on the digits the long double - // is accurate for. + written = LIBC_NAMESPACE::sprintf(buff, "%15f", 1.0); + ASSERT_STREQ_LEN(written, buff, " 1.000000"); - written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1.0L); - ASSERT_STREQ_LEN(written, buff, "1.000000"); + written = LIBC_NAMESPACE::sprintf(buff, "%15f", -1.0); + ASSERT_STREQ_LEN(written, buff, " -1.000000"); - written = LIBC_NAMESPACE::sprintf(buff, "%.Lf", -2.5L); - ASSERT_STREQ_LEN(written, buff, "-2"); + written = LIBC_NAMESPACE::sprintf(buff, "%15f", 1.0e5); + ASSERT_STREQ_LEN(written, buff, " 100000.000000"); -#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + written = LIBC_NAMESPACE::sprintf(buff, "%15f", -1.0e5); + ASSERT_STREQ_LEN(written, buff, " -100000.000000"); - written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L); - ASSERT_STREQ_LEN(written, buff, - "99999999999999999996693535322073426194986990198284960792713" - "91541752018669482644324418977840117055488.000000"); + written = LIBC_NAMESPACE::sprintf(buff, "%10f", 1.0e5); + ASSERT_STREQ_LEN(written, buff, "100000.000000"); - written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e1000L); - ASSERT_STREQ_LEN( - written, big_buff, - "999999999999999999973107317669562353428234857594552594925899449376328728" - "202461036775511405481186963193066642191664822065529414252060696836533522" - "387143501724276282079456797058697369889056407118642873669166717313763499" - "277025985141177344925615052465165938514140943010597323750202561187880136" - "174810574553749194614479541820148407958204853833697063267336294787191005" - "628217462261955103745349844675732989944229689277833828743730290177882029" - "042613704915899149603539993716885598351951895974316347947147507970269673" - "097709017164643598452451201499004104341931127294141495501309305995449742" - "273419524803597130450457553871345958049837885085168840317195672271085085" - "950520957945970913451088104971436093671776829538796532762184174216651692" - "640931965387852083906784898823494867055070322768919156031682291829761007" - "101483799978382119231551218582499361996919560548090784230386907125151658" - "086767207295524036170321059257942621398084478974000973622199163292708506" - "2431457550909271560663602154947063707982236377366647567795879936." - "000000"); + // Precision Tests. - written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e4900L); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.0); + ASSERT_STREQ_LEN(written, buff, "1.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 0.0); + ASSERT_STREQ_LEN(written, buff, "0.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 0.0); + ASSERT_STREQ_LEN(written, buff, "0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 0.1); + ASSERT_STREQ_LEN(written, buff, "0.1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.09); + ASSERT_STREQ_LEN(written, buff, "1.1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.04); + ASSERT_STREQ_LEN(written, buff, "1.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.19); + ASSERT_STREQ_LEN(written, buff, "1.2"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.99); + ASSERT_STREQ_LEN(written, buff, "2.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 9.99); + ASSERT_STREQ_LEN(written, buff, "10.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.2f", 9999999999999.99); + ASSERT_STREQ_LEN(written, buff, "9999999999999.99"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 9999999999999.99); + ASSERT_STREQ_LEN(written, buff, "10000000000000.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 1.25); + ASSERT_STREQ_LEN(written, buff, "1.25000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 1.25); + ASSERT_STREQ_LEN(written, buff, "1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 1.75); + ASSERT_STREQ_LEN(written, buff, "2"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.20f", 1.234e-10); + ASSERT_STREQ_LEN(written, buff, "0.00000000012340000000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.2f", -9.99); + ASSERT_STREQ_LEN(written, buff, "-9.99"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -9.99); + ASSERT_STREQ_LEN(written, buff, "-10.0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 0.0); + ASSERT_STREQ_LEN(written, buff, "0.00000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 1.008); + ASSERT_STREQ_LEN(written, buff, "1.00800"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 1.008e3); + ASSERT_STREQ_LEN(written, buff, "1008.00000"); + + // Found with the help of Fred Tydeman's tbin2dec test. + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 0x1.1000000000006p+3); + ASSERT_STREQ_LEN(written, buff, "8.5"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 0x1.1000000000006p+3); + ASSERT_STREQ_LEN(written, buff, "9"); + + // Most of these tests are checking rounding behavior when the precision is + // set. As an example, %.9f has a precision of 9, meaning it should be rounded + // to 9 digits after the decimal point. In this case, that means that it + // should be rounded up. Many of these tests have precisions divisible by 9 + // since when printing the floating point numbers are broken up into "blocks" + // of 9 digits. They often also have a 5 after the end of what's printed, + // since in round to nearest mode, that requires checking additional digits. + written = LIBC_NAMESPACE::sprintf(buff, "%.9f", 1.9999999999999514); + ASSERT_STREQ_LEN(written, buff, "2.000000000"); + + // The number continues after the literal because floating point numbers can't + // represent every value. The printed value is the closest value a double can + // represent, rounded to the requested precision. + written = LIBC_NAMESPACE::sprintf(buff, "%.238f", 1.131959884853339E-72); ASSERT_STREQ_LEN( - written, big_buff, - "100000000000000000002708312230690349833224052504078834346502930111959028" - "517260692666637048230414374897655201843766090626319971729765251179632020" - "313912652522792711197087872698264530532442630109549129842736280196919130" - "242615101228133188193853826983121366159061148351354364472807590931218045" - "387490935930967150336231085015126034696883068553581691802388371635128003" - "615577299166097675723780877126495909902479233742826339471026068806070433" - "075629449530819183550315434973800271862658869400009022028602967197463980" - "126881829804282202449930132940824361207087494829502385835258094836304011" - "876250359661206802659650567866176246063987902366800491980400341950657151" - "370854446585517805253310195469184699955519312761482572080479702840420595" - "377369017651259376039167277822106875560385309101650382998482652792335482" - "865443482342801545877390859444282105890147577937366066315975231014810320" - "888482059656248277607763361589359794524314002443575149260630989130103550" - "443177966380769341050735632338583912575890190136462629316287947355057647" - "111088565611192544631519843618778618820046304429723908484879583579178075" - "456701368334212923379389029311286386996015804122917416008806233549005183" - "152461084266176543129004016414959261473645240454289630182591200574019087" - "358223489767381636349719510715487188747217311279465814538495924567014916" - "238565628036285599497236493491668884212847699052761266207598941300449276" - "447201387520841811835583254242213093566548778954711633721122784159793843" - "766802019309395771984693609426401362800013936338891483689127845928572536" - "790651156184721483511507878883282891696900630100211914227950790472211403" - "392549466062537498185758854079775888444518306635752468713312357556380082" - "275500658967283696421824354930077523691855699312544373220921962817907078" - "445538421941800259027487429330768616490865438859612697367766323925013940" - "918384858952407145253573823848733994146335416209309233074165707437420756" - "438833918763109580759409985573826485055208965115587885226774453455112406" - "581351429640282227888764449360534584421929291565334894907337572527922691" - "473242328379737396430908523008687037407295838014450772162091496534584696" - "605157436893236842602956298545594095307060870397506421786236892553632163" - "491468601982681381011940409602294892199042638682530687578982576819839451" - "907594697546439533559153604700750696252355362322662219852740143212566818" - "745528402265116534684566273868361460640280523251242059850044328669692159" - "629900374576027104298177006629276014371540945261309319363704125592775129" - "543526908667388673739382491147471395192495459318806593271282662311169392" - "196897003517840025298267505925987901751541005546610016067658227181318892" - "914686508281007582655667597441346214499847364272258631922040641860333431" - "409838623713258383681350233064164940590695888300919626215847587544298023" - "636416943680102708406086295669759876682046839368574433996997648445207805" - "615784339667691231286807666753972942872019850432610318031627872612657513" - "588188267160616660825719678199868371370527508463011236193719286066916786" - "169956541349011494927225747024994619057884118692213564790598702879596058" - "672338334720925179141906809470606964896245458600635183723159228561689808" - "246141482736625197373238197777325580142168245885279594913851700941789475" - "252421784152262567254611571822468808675893407728003047921107885664474662" - "930921581384003950729114103689170603748380178682003976896397305836815761" - "717676338115866650889936516794601457549097578905329423919798362140648664" - "569177147076571576101649257502509463877402424847669830852345415301684820" - "395813946416649808062227494112874521812750160935760825922220707178083076" - "380203450993589198835885505461509442443773367592842795410339065860781804" - "024975272228687688301824830333940416256885455008512598774611538878683158" - "183931461086893832255176926531299425504132104728730288984598001187854507" - "900417184206801359847651992484444933900133130832052346600926424167009902" - "829803553087005800387704758687923428053612864451456596148162238935900033" - "917094683141205188616000211702577553792389670853917118547527592495253773" - "028135298405566315903922235989614934474805789300370437580494193066066314" - "056627605207631392651010580925826419831250810981343093764403877594495896" - "516881097415880926429607388979497471571321217205535961262051641426436441" - "668989765107456413733909427384182109285933511623871034309722437967253289" - "084018145083721513211807496392673952789642893241520398827805325610653506" - "029060153153064455898648607959013571280930834475689835845791849456112104" - "462337569019001580859906425911782967213265389744605395555069797947978230" - "708108432086217134763779632408473684293543722127232658767439906910370146" - "716836295909075482355827087389127370874842532825987593970846704144140471" - "956027276735614286138656432085771988513977140957180090146798065497158947" - "229765733489703157617307078835099906185890777007500964162371428641176460" - "739074789794941408428328217107759915202650066155868439585510978709442590" - "231934194956788626761834746430104077432547436359522462253411168467463134" - "24896.000000"); + written, buff, + "0." + "000000000000000000000000000000000000000000000000000000000000000000000001" + "131959884853339045938639911360973972585316399767392273697826861241937664" + "824105639342441431495119762431744054912109728706985341609159156917030486" + "5110665559768676757812"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.36f", 9.9e-77); + ASSERT_STREQ_LEN(written, buff, "0.000000000000000000000000000000000000"); written = - LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 0xf.fffffffffffffffp+16380L); - ASSERT_STREQ_LEN( - written, big_buff, - "118973149535723176502126385303097020516906332229462420044032373389173700" - "552297072261641029033652888285354569780749557731442744315367028843419812" - "557385374367867359320070697326320191591828296152436552951064679108661431" - "179063216977883889613478656060039914875343321145491116008867984515486651" - "285234014977303760000912547939396622315138362241783854274391783813871780" - "588948754057516822634765923557697480511372564902088485522249479139937758" - "502601177354918009979622602685950855888360815984690023564513234659447638" - "493985927645628457966177293040780660922910271504608538808795932778162298" - "682754783076808004015069494230341172895777710033571401055977524212405734" - "700738625166011082837911962300846927720096515350020847447079244384854591" - "288672300061908512647211195136146752763351956292759795725027800298079590" - "419313960302147099703527646744553092202267965628099149823208332964124103" - "850923918473478612192169721054348428704835340811304257300221642134891734" - "717423480071488075100206439051723424765600472176809648610799494341570347" - "632064355862420744350442438056613601760883747816538902780957697597728686" - "007148702828795556714140463261583262360276289631617397848425448686060994" - "827086796804807870251185893083854658422304090880599629459458620190376604" - "844679092600222541053077590106576067134720012584640695703025713896098375" - "799892695455305236856075868317922311363951946885088077187210470520395758" - "748001314313144425494391994017575316933939236688185618912993172910425292" - "123683515992232205099800167710278403536014082929639811512287776813570604" - "578934353545169653956125404884644716978689321167108722908808277835051822" - "885764606221873970285165508372099234948333443522898475123275372663606621" - "390228126470623407535207172405866507951821730346378263135339370677490195" - "019784169044182473806316282858685774143258116536404021840272491339332094" - "921949842244273042701987304453662035026238695780468200360144729199712309" - "553005720614186697485284685618651483271597448120312194675168637934309618" - "961510733006555242148519520176285859509105183947250286387163249416761380" - "499631979144187025430270675849519200883791516940158174004671147787720145" - "964446117520405945350476472180797576111172084627363927960033967047003761" - "337450955318415007379641260504792325166135484129188421134082301547330475" - "406707281876350361733290800595189632520707167390454777712968226520622565" - "143991937680440029238090311243791261477625596469422198137514696707944687" - "035800439250765945161837981185939204954403611491531078225107269148697980" - "924094677214272701240437718740921675661363493890045123235166814608932240" - "069799317601780533819184998193300841098599393876029260139091141452600372" - "028487213241195542428210183120421610446740462163533690058366460659115629" - "876474552506814500393294140413149540067760295100596225302282300363147382" - "468105964844244132486457313743759509641616804802412935187620466813563687" - "753281467553879887177183651289394719533506188500326760735438867336800207" - "438784965701457609034985757124304510203873049485425670247933932280911052" - "604153852899484920399109194612991249163328991799809438033787952209313146" - "694614970593966415237594928589096048991612194498998638483702248667224914" - "892467841020618336462741696957630763248023558797524525373703543388296086" - "275342774001633343405508353704850737454481975472222897528108302089868263" - "302028525992308416805453968791141829762998896457648276528750456285492426" - "516521775079951625966922911497778896235667095662713848201819134832168799" - "586365263762097828507009933729439678463987902491451422274252700636394232" - "799848397673998715441855420156224415492665301451550468548925862027608576" - "183712976335876121538256512963353814166394951655600026415918655485005705" - "261143195291991880795452239464962763563017858089669222640623538289853586" - "759599064700838568712381032959192649484625076899225841930548076362021508" - "902214922052806984201835084058693849381549890944546197789302911357651677" - "540623227829831403347327660395223160342282471752818181884430488092132193" - "355086987339586127607367086665237555567580317149010847732009642431878007" - "000879734603290627894355374356444885190719161645514115576193939969076741" - "515640282654366402676009508752394550734155613586793306603174472092444651" - "353236664764973540085196704077110364053815007348689179836404957060618953" - "500508984091382686953509006678332447257871219660441528492484004185093281" - "190896363417573989716659600075948780061916409485433875852065711654107226" - "099628815012314437794400874930194474433078438899570184271000480830501217" - "712356062289507626904285680004771889315808935851559386317665294808903126" - "774702966254511086154895839508779675546413794489596052797520987481383976" - "257859210575628440175934932416214833956535018919681138909184379573470326" - "940634289008780584694035245347939808067427323629788710086717580253156130" - "235606487870925986528841635097252953709111431720488774740553905400942537" - "542411931794417513706468964386151771884986701034153254238591108962471088" - "538580868883777725864856414593426212108664758848926003176234596076950884" - "9149662444156604419552086811989770240.000000"); - - written = LIBC_NAMESPACE::sprintf(big_buff, "%.10Lf", 1e-10L); - ASSERT_STREQ_LEN(written, big_buff, "0.0000000001"); - - written = LIBC_NAMESPACE::sprintf(big_buff, "%.7500Lf", 1e-4900L); + LIBC_NAMESPACE::sprintf(big_buff, "%.1071f", 2.0226568751604562E-314); ASSERT_STREQ_LEN( written, big_buff, "0." @@ -1233,401 +1156,149 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) { "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000020226568751604561683387695750739190248658016786" + "876938365740768295004457513021760887468117675879956193821375945376632621" + "367998639317487303530427946024002091961988296562516210434394107910027236" + "308233439098296717697919471698168200340836487924061502604112643734560622" + "258525943451473162532620033398739382796482175564084902819878893430369431" + "907237673154867595954110791891883281880339550955455702452422857027182100" + "606009588295886640782228837851739241290179512817803196347460636150182981" + "085084829941917048152725177119574542042352896161225179181967347829576272" + "242480201291872969114441104973910102402751449901108484914924879541248714" + "939096548775588293353689592872854495101242645279589976452453829724479805" + "750016448075109469332839157162950982637994457036256790161132812"); + + // If no precision is specified it defaults to 6 for %f. + written = LIBC_NAMESPACE::sprintf(buff, "%f", 2325885.4901960781); + ASSERT_STREQ_LEN(written, buff, "2325885.490196"); + + // Subnormal Precision Tests + + written = LIBC_NAMESPACE::sprintf(buff, "%.310f", 0x1.0p-1022); + ASSERT_STREQ_LEN( + written, buff, + "0." "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000223"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.310f", 0x1.0p-1023); + ASSERT_STREQ_LEN( + written, buff, + "0." "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" + "0000000000000000000111"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.315f", 9.99999e-310); + ASSERT_STREQ_LEN( + written, buff, + "0." "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000999999"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.314f", 9.99999e-310); + ASSERT_STREQ_LEN( + written, buff, + "0." "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000100000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.330f", 0x1.0p-1074); + ASSERT_STREQ_LEN( + written, buff, + "0." "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000099999999999999999996962764452956071352139203248614920751610856665084" - "549214352477698417183862158583009348897567779527408501588132175167211539" - "462139941448204886585901454195352527238724272760638086779284030512649793" - "039219351187928723378036480041948464946018272171365770411701020666925613" - "422460317465324758217878522666789603627480490870456508256359180089236338" - "765625231186929290294207420828927406735690318849109129700396907705735097" - "663944722727287361650042373203763784830198232253311807069225650324196304" - "532045014970637489181357566354288111205943347410488298480279857453705249" - "232862728556860184412369114663536200895729846877559808001004454634804626" - "541455540260282018142615835686583304903486353937549394736905011798466731" - "536563240053860118551127061960208467764243724656897127545613968909523389" - "577188368809623987105800147797280462974804046545425080530020901531407223" - "191237123282274818236437397994019915368657474589800678444589412286037789" - "891525464936023205313685584525510094270344601331453730179416773626565262" - "480345858564672442896904520146956686863172737711483866766404977719744767" - "834324844875237277613991088218774564658513875732403456058414595576806383" - "115554713240005982141397577420073082470139244845624915873825746771661332" - "098677966580506186966978746832443976821987300902957597498388211921362869" - "017846215557612829071692275292036211064515305528052919611691470945774714" - "135516559501572279732350629089770249554808690411603894492333360300589658" - "470898965370892774715815089075170720164713889237058574941489766701880158" - "060081295483989540170337129032188818293132770882381428397119039835946745" - "549356649433406617266370644136291924838857814675939156677910783740103207" - "523299367093130816446415259371931925208362367989095199399211644084543790" - "110432339056231037520216864358899218874658268610955002763260912337688947" - "822453100821038299301092582962825965939081817836419126254832772002214908" - "085575905761843610944187009818156363893015929300295112598059949496854566" - "638748010633726861510500653821408135845840123073754133549077708843800674" - "328440913743105608636458354618912183716456158809545183074062249922212944" - "249667793845728355381309084891765979111348980470647082269921872595470473" - "719354467594516320911964549508538492057120740224559944452120552719041944" - "961475548547884309626382512432626380881023756568143060204097921571153170" - "723817845809196253498326358439807445210362177680590181657555380795450462" - "223805222580359379367452693270553602179122419370586308101820559214330382" - "570449525088342437216896462077260223998756027453411520977536701491759878" - "422771447006016890777855573925295187921971811871399320142563330377888532" - "179817332113"); -#endif // LIBC_LONG_DOUBLE_IS_X86_FLOAT80 + "000000000000000000000000000000000004940656"); /* - written = LIBC_NAMESPACE::sprintf(buff, "%La", 0.1L); + written = LIBC_NAMESPACE::sprintf(buff, "%.1La", 0.1L); #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7"); + ASSERT_STREQ_LEN(written, buff, "0xc.dp-7"); #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4"); + ASSERT_STREQ_LEN(written, buff, "0x1.ap-4"); #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4"); + ASSERT_STREQ_LEN(written, buff, "0x1.ap-4"); #endif - written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e1000L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1La", + 0xf.fffffffffffffffp16380L); #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0x1.0p+16384"); #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) ASSERT_STREQ_LEN(written, buff, "inf"); #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321"); - #endif - - written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e-1000L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x0p+0"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322"); + ASSERT_STREQ_LEN(written, buff, "0x2.0p+16383"); #endif */ - // Min Width Tests. - - written = LIBC_NAMESPACE::sprintf(buff, "%15f", 1.0); - ASSERT_STREQ_LEN(written, buff, " 1.000000"); + // Rounding Mode Tests. - written = LIBC_NAMESPACE::sprintf(buff, "%15f", -1.0); - ASSERT_STREQ_LEN(written, buff, " -1.000000"); + if (ForceRoundingMode r(RoundingMode::Nearest); r.success) { + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.75); + ASSERT_STREQ_LEN(written, buff, "1.8"); - written = LIBC_NAMESPACE::sprintf(buff, "%15f", 1.0e5); - ASSERT_STREQ_LEN(written, buff, " 100000.000000"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.25); + ASSERT_STREQ_LEN(written, buff, "1.2"); - written = LIBC_NAMESPACE::sprintf(buff, "%15f", -1.0e5); - ASSERT_STREQ_LEN(written, buff, " -100000.000000"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.125); + ASSERT_STREQ_LEN(written, buff, "1.1"); - written = LIBC_NAMESPACE::sprintf(buff, "%10f", 1.0e5); - ASSERT_STREQ_LEN(written, buff, "100000.000000"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.625); + ASSERT_STREQ_LEN(written, buff, "1.6"); - // Precision Tests. + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.375); + ASSERT_STREQ_LEN(written, buff, "1.4"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.0); - ASSERT_STREQ_LEN(written, buff, "1.0"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.875); + ASSERT_STREQ_LEN(written, buff, "1.9"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 0.0); - ASSERT_STREQ_LEN(written, buff, "0.0"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.75); + ASSERT_STREQ_LEN(written, buff, "-1.8"); - written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 0.0); - ASSERT_STREQ_LEN(written, buff, "0"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.25); + ASSERT_STREQ_LEN(written, buff, "-1.2"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 0.1); - ASSERT_STREQ_LEN(written, buff, "0.1"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.125); + ASSERT_STREQ_LEN(written, buff, "-1.1"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.09); - ASSERT_STREQ_LEN(written, buff, "1.1"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.625); + ASSERT_STREQ_LEN(written, buff, "-1.6"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.04); - ASSERT_STREQ_LEN(written, buff, "1.0"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.375); + ASSERT_STREQ_LEN(written, buff, "-1.4"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.19); - ASSERT_STREQ_LEN(written, buff, "1.2"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.875); + ASSERT_STREQ_LEN(written, buff, "-1.9"); + } - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.99); - ASSERT_STREQ_LEN(written, buff, "2.0"); + if (ForceRoundingMode r(RoundingMode::Upward); r.success) { + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.75); + ASSERT_STREQ_LEN(written, buff, "1.8"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 9.99); - ASSERT_STREQ_LEN(written, buff, "10.0"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.25); + ASSERT_STREQ_LEN(written, buff, "1.3"); - written = LIBC_NAMESPACE::sprintf(buff, "%.2f", 9999999999999.99); - ASSERT_STREQ_LEN(written, buff, "9999999999999.99"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.125); + ASSERT_STREQ_LEN(written, buff, "1.2"); - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 9999999999999.99); - ASSERT_STREQ_LEN(written, buff, "10000000000000.0"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.625); + ASSERT_STREQ_LEN(written, buff, "1.7"); - written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 1.25); - ASSERT_STREQ_LEN(written, buff, "1.25000"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 1.25); - ASSERT_STREQ_LEN(written, buff, "1"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 1.75); - ASSERT_STREQ_LEN(written, buff, "2"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.20f", 1.234e-10); - ASSERT_STREQ_LEN(written, buff, "0.00000000012340000000"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.2f", -9.99); - ASSERT_STREQ_LEN(written, buff, "-9.99"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -9.99); - ASSERT_STREQ_LEN(written, buff, "-10.0"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 0.0); - ASSERT_STREQ_LEN(written, buff, "0.00000"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 1.008); - ASSERT_STREQ_LEN(written, buff, "1.00800"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.5f", 1.008e3); - ASSERT_STREQ_LEN(written, buff, "1008.00000"); - - // Found with the help of Fred Tydeman's tbin2dec test. - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 0x1.1000000000006p+3); - ASSERT_STREQ_LEN(written, buff, "8.5"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.0f", 0x1.1000000000006p+3); - ASSERT_STREQ_LEN(written, buff, "9"); - - // Most of these tests are checking rounding behavior when the precision is - // set. As an example, %.9f has a precision of 9, meaning it should be rounded - // to 9 digits after the decimal point. In this case, that means that it - // should be rounded up. Many of these tests have precisions divisible by 9 - // since when printing the floating point numbers are broken up into "blocks" - // of 9 digits. They often also have a 5 after the end of what's printed, - // since in round to nearest mode, that requires checking additional digits. - written = LIBC_NAMESPACE::sprintf(buff, "%.9f", 1.9999999999999514); - ASSERT_STREQ_LEN(written, buff, "2.000000000"); - - // The number continues after the literal because floating point numbers can't - // represent every value. The printed value is the closest value a double can - // represent, rounded to the requested precision. - written = LIBC_NAMESPACE::sprintf(buff, "%.238f", 1.131959884853339E-72); - ASSERT_STREQ_LEN( - written, buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000001" - "131959884853339045938639911360973972585316399767392273697826861241937664" - "824105639342441431495119762431744054912109728706985341609159156917030486" - "5110665559768676757812"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.36f", 9.9e-77); - ASSERT_STREQ_LEN(written, buff, "0.000000000000000000000000000000000000"); - - written = - LIBC_NAMESPACE::sprintf(big_buff, "%.1071f", 2.0226568751604562E-314); - ASSERT_STREQ_LEN( - written, big_buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000020226568751604561683387695750739190248658016786" - "876938365740768295004457513021760887468117675879956193821375945376632621" - "367998639317487303530427946024002091961988296562516210434394107910027236" - "308233439098296717697919471698168200340836487924061502604112643734560622" - "258525943451473162532620033398739382796482175564084902819878893430369431" - "907237673154867595954110791891883281880339550955455702452422857027182100" - "606009588295886640782228837851739241290179512817803196347460636150182981" - "085084829941917048152725177119574542042352896161225179181967347829576272" - "242480201291872969114441104973910102402751449901108484914924879541248714" - "939096548775588293353689592872854495101242645279589976452453829724479805" - "750016448075109469332839157162950982637994457036256790161132812"); - - // If no precision is specified it defaults to 6 for %f. - written = LIBC_NAMESPACE::sprintf(buff, "%f", 2325885.4901960781); - ASSERT_STREQ_LEN(written, buff, "2325885.490196"); - - // Subnormal Precision Tests - - written = LIBC_NAMESPACE::sprintf(buff, "%.310f", 0x1.0p-1022); - ASSERT_STREQ_LEN( - written, buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000223"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.310f", 0x1.0p-1023); - ASSERT_STREQ_LEN( - written, buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "0000000000000000000111"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.315f", 9.99999e-310); - ASSERT_STREQ_LEN( - written, buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000999999"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.314f", 9.99999e-310); - ASSERT_STREQ_LEN( - written, buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "00000000000000000000100000"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.330f", 0x1.0p-1074); - ASSERT_STREQ_LEN( - written, buff, - "0." - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000004940656"); - - /* - written = LIBC_NAMESPACE::sprintf(buff, "%.1La", 0.1L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xc.dp-7"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x1.ap-4"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.ap-4"); - #endif - - written = LIBC_NAMESPACE::sprintf(buff, "%.1La", - 0xf.fffffffffffffffp16380L); #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0x1.0p+16384"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "inf"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x2.0p+16383"); - #endif - */ - - // Rounding Mode Tests. - - if (ForceRoundingMode r(RoundingMode::Nearest); r.success) { - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.75); - ASSERT_STREQ_LEN(written, buff, "1.8"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.25); - ASSERT_STREQ_LEN(written, buff, "1.2"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.125); - ASSERT_STREQ_LEN(written, buff, "1.1"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.625); - ASSERT_STREQ_LEN(written, buff, "1.6"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.375); - ASSERT_STREQ_LEN(written, buff, "1.4"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.875); - ASSERT_STREQ_LEN(written, buff, "1.9"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.75); - ASSERT_STREQ_LEN(written, buff, "-1.8"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.25); - ASSERT_STREQ_LEN(written, buff, "-1.2"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.125); - ASSERT_STREQ_LEN(written, buff, "-1.1"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.625); - ASSERT_STREQ_LEN(written, buff, "-1.6"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.375); - ASSERT_STREQ_LEN(written, buff, "-1.4"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", -1.875); - ASSERT_STREQ_LEN(written, buff, "-1.9"); - } - - if (ForceRoundingMode r(RoundingMode::Upward); r.success) { - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.75); - ASSERT_STREQ_LEN(written, buff, "1.8"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.25); - ASSERT_STREQ_LEN(written, buff, "1.3"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.125); - ASSERT_STREQ_LEN(written, buff, "1.2"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.625); - ASSERT_STREQ_LEN(written, buff, "1.7"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.375); - ASSERT_STREQ_LEN(written, buff, "1.4"); + written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.375); + ASSERT_STREQ_LEN(written, buff, "1.4"); written = LIBC_NAMESPACE::sprintf(buff, "%.1f", 1.875); ASSERT_STREQ_LEN(written, buff, "1.9"); @@ -1794,6 +1465,346 @@ TEST_F(LlvmLibcSPrintfTest, FloatDecimalConv) { ASSERT_STREQ_LEN(written, buff, "+0.126 0001256.000"); } +// The long double tests are separated so that their performance can be directly +// measured. +TEST_F(LlvmLibcSPrintfTest, FloatDecimalLongDoubleConv) { + ForceRoundingMode r(RoundingMode::Nearest); + + char big_buff[10000]; // Used for long doubles and other extremely wide + // numbers. + + // Length Modifier Tests. + + // TODO(michaelrj): Add tests for LIBC_LONG_DOUBLE_IS_FLOAT64 and 128 bit long + // double systems. + // TODO(michaelrj): Fix the tests to only depend on the digits the long double + // is accurate for. + + written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1.0L); + ASSERT_STREQ_LEN(written, buff, "1.000000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.Lf", -2.5L); + ASSERT_STREQ_LEN(written, buff, "-2"); + +#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + + written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L); + ASSERT_STREQ_LEN(written, buff, + "99999999999999999996693535322073426194986990198284960792713" + "91541752018669482644324418977840117055488.000000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 0xd.96ed1192687859ap-24L); + ASSERT_STREQ_LEN(written, buff, "0.000001"); + + written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 10000000000000000.25L); + ASSERT_STREQ_LEN(written, buff, "10000000000000000.250000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.510Lf", 0x8p-503L); + ASSERT_STREQ_LEN( + written, buff, + "0." + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000305493636349960468205197939321361769978940274057232666389361390928" + "129162652472045770185723510801522825687515269359046715531785342780428396" + "973513311420091788963072442053377285222203558881953188370081650866793017" + "948791366338993705251636497892270212003524508209121908744820211960149463" + "721109340307985507678283651836204093399373959982767701148986816406250000" + "000000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%.500Lf", -4327677766926336.0L); + ASSERT_STREQ_LEN( + written, buff, + "-4327677766926336." + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000000"); + + written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e1000L); + ASSERT_STREQ_LEN( + written, big_buff, + "999999999999999999973107317669562353428234857594552594925899449376328728" + "202461036775511405481186963193066642191664822065529414252060696836533522" + "387143501724276282079456797058697369889056407118642873669166717313763499" + "277025985141177344925615052465165938514140943010597323750202561187880136" + "174810574553749194614479541820148407958204853833697063267336294787191005" + "628217462261955103745349844675732989944229689277833828743730290177882029" + "042613704915899149603539993716885598351951895974316347947147507970269673" + "097709017164643598452451201499004104341931127294141495501309305995449742" + "273419524803597130450457553871345958049837885085168840317195672271085085" + "950520957945970913451088104971436093671776829538796532762184174216651692" + "640931965387852083906784898823494867055070322768919156031682291829761007" + "101483799978382119231551218582499361996919560548090784230386907125151658" + "086767207295524036170321059257942621398084478974000973622199163292708506" + "2431457550909271560663602154947063707982236377366647567795879936." + "000000"); + + written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e4900L); + ASSERT_STREQ_LEN( + written, big_buff, + "100000000000000000002708312230690349833224052504078834346502930111959028" + "517260692666637048230414374897655201843766090626319971729765251179632020" + "313912652522792711197087872698264530532442630109549129842736280196919130" + "242615101228133188193853826983121366159061148351354364472807590931218045" + "387490935930967150336231085015126034696883068553581691802388371635128003" + "615577299166097675723780877126495909902479233742826339471026068806070433" + "075629449530819183550315434973800271862658869400009022028602967197463980" + "126881829804282202449930132940824361207087494829502385835258094836304011" + "876250359661206802659650567866176246063987902366800491980400341950657151" + "370854446585517805253310195469184699955519312761482572080479702840420595" + "377369017651259376039167277822106875560385309101650382998482652792335482" + "865443482342801545877390859444282105890147577937366066315975231014810320" + "888482059656248277607763361589359794524314002443575149260630989130103550" + "443177966380769341050735632338583912575890190136462629316287947355057647" + "111088565611192544631519843618778618820046304429723908484879583579178075" + "456701368334212923379389029311286386996015804122917416008806233549005183" + "152461084266176543129004016414959261473645240454289630182591200574019087" + "358223489767381636349719510715487188747217311279465814538495924567014916" + "238565628036285599497236493491668884212847699052761266207598941300449276" + "447201387520841811835583254242213093566548778954711633721122784159793843" + "766802019309395771984693609426401362800013936338891483689127845928572536" + "790651156184721483511507878883282891696900630100211914227950790472211403" + "392549466062537498185758854079775888444518306635752468713312357556380082" + "275500658967283696421824354930077523691855699312544373220921962817907078" + "445538421941800259027487429330768616490865438859612697367766323925013940" + "918384858952407145253573823848733994146335416209309233074165707437420756" + "438833918763109580759409985573826485055208965115587885226774453455112406" + "581351429640282227888764449360534584421929291565334894907337572527922691" + "473242328379737396430908523008687037407295838014450772162091496534584696" + "605157436893236842602956298545594095307060870397506421786236892553632163" + "491468601982681381011940409602294892199042638682530687578982576819839451" + "907594697546439533559153604700750696252355362322662219852740143212566818" + "745528402265116534684566273868361460640280523251242059850044328669692159" + "629900374576027104298177006629276014371540945261309319363704125592775129" + "543526908667388673739382491147471395192495459318806593271282662311169392" + "196897003517840025298267505925987901751541005546610016067658227181318892" + "914686508281007582655667597441346214499847364272258631922040641860333431" + "409838623713258383681350233064164940590695888300919626215847587544298023" + "636416943680102708406086295669759876682046839368574433996997648445207805" + "615784339667691231286807666753972942872019850432610318031627872612657513" + "588188267160616660825719678199868371370527508463011236193719286066916786" + "169956541349011494927225747024994619057884118692213564790598702879596058" + "672338334720925179141906809470606964896245458600635183723159228561689808" + "246141482736625197373238197777325580142168245885279594913851700941789475" + "252421784152262567254611571822468808675893407728003047921107885664474662" + "930921581384003950729114103689170603748380178682003976896397305836815761" + "717676338115866650889936516794601457549097578905329423919798362140648664" + "569177147076571576101649257502509463877402424847669830852345415301684820" + "395813946416649808062227494112874521812750160935760825922220707178083076" + "380203450993589198835885505461509442443773367592842795410339065860781804" + "024975272228687688301824830333940416256885455008512598774611538878683158" + "183931461086893832255176926531299425504132104728730288984598001187854507" + "900417184206801359847651992484444933900133130832052346600926424167009902" + "829803553087005800387704758687923428053612864451456596148162238935900033" + "917094683141205188616000211702577553792389670853917118547527592495253773" + "028135298405566315903922235989614934474805789300370437580494193066066314" + "056627605207631392651010580925826419831250810981343093764403877594495896" + "516881097415880926429607388979497471571321217205535961262051641426436441" + "668989765107456413733909427384182109285933511623871034309722437967253289" + "084018145083721513211807496392673952789642893241520398827805325610653506" + "029060153153064455898648607959013571280930834475689835845791849456112104" + "462337569019001580859906425911782967213265389744605395555069797947978230" + "708108432086217134763779632408473684293543722127232658767439906910370146" + "716836295909075482355827087389127370874842532825987593970846704144140471" + "956027276735614286138656432085771988513977140957180090146798065497158947" + "229765733489703157617307078835099906185890777007500964162371428641176460" + "739074789794941408428328217107759915202650066155868439585510978709442590" + "231934194956788626761834746430104077432547436359522462253411168467463134" + "24896.000000"); + + written = + LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 0xf.fffffffffffffffp+16380L); + ASSERT_STREQ_LEN( + written, big_buff, + "118973149535723176502126385303097020516906332229462420044032373389173700" + "552297072261641029033652888285354569780749557731442744315367028843419812" + "557385374367867359320070697326320191591828296152436552951064679108661431" + "179063216977883889613478656060039914875343321145491116008867984515486651" + "285234014977303760000912547939396622315138362241783854274391783813871780" + "588948754057516822634765923557697480511372564902088485522249479139937758" + "502601177354918009979622602685950855888360815984690023564513234659447638" + "493985927645628457966177293040780660922910271504608538808795932778162298" + "682754783076808004015069494230341172895777710033571401055977524212405734" + "700738625166011082837911962300846927720096515350020847447079244384854591" + "288672300061908512647211195136146752763351956292759795725027800298079590" + "419313960302147099703527646744553092202267965628099149823208332964124103" + "850923918473478612192169721054348428704835340811304257300221642134891734" + "717423480071488075100206439051723424765600472176809648610799494341570347" + "632064355862420744350442438056613601760883747816538902780957697597728686" + "007148702828795556714140463261583262360276289631617397848425448686060994" + "827086796804807870251185893083854658422304090880599629459458620190376604" + "844679092600222541053077590106576067134720012584640695703025713896098375" + "799892695455305236856075868317922311363951946885088077187210470520395758" + "748001314313144425494391994017575316933939236688185618912993172910425292" + "123683515992232205099800167710278403536014082929639811512287776813570604" + "578934353545169653956125404884644716978689321167108722908808277835051822" + "885764606221873970285165508372099234948333443522898475123275372663606621" + "390228126470623407535207172405866507951821730346378263135339370677490195" + "019784169044182473806316282858685774143258116536404021840272491339332094" + "921949842244273042701987304453662035026238695780468200360144729199712309" + "553005720614186697485284685618651483271597448120312194675168637934309618" + "961510733006555242148519520176285859509105183947250286387163249416761380" + "499631979144187025430270675849519200883791516940158174004671147787720145" + "964446117520405945350476472180797576111172084627363927960033967047003761" + "337450955318415007379641260504792325166135484129188421134082301547330475" + "406707281876350361733290800595189632520707167390454777712968226520622565" + "143991937680440029238090311243791261477625596469422198137514696707944687" + "035800439250765945161837981185939204954403611491531078225107269148697980" + "924094677214272701240437718740921675661363493890045123235166814608932240" + "069799317601780533819184998193300841098599393876029260139091141452600372" + "028487213241195542428210183120421610446740462163533690058366460659115629" + "876474552506814500393294140413149540067760295100596225302282300363147382" + "468105964844244132486457313743759509641616804802412935187620466813563687" + "753281467553879887177183651289394719533506188500326760735438867336800207" + "438784965701457609034985757124304510203873049485425670247933932280911052" + "604153852899484920399109194612991249163328991799809438033787952209313146" + "694614970593966415237594928589096048991612194498998638483702248667224914" + "892467841020618336462741696957630763248023558797524525373703543388296086" + "275342774001633343405508353704850737454481975472222897528108302089868263" + "302028525992308416805453968791141829762998896457648276528750456285492426" + "516521775079951625966922911497778896235667095662713848201819134832168799" + "586365263762097828507009933729439678463987902491451422274252700636394232" + "799848397673998715441855420156224415492665301451550468548925862027608576" + "183712976335876121538256512963353814166394951655600026415918655485005705" + "261143195291991880795452239464962763563017858089669222640623538289853586" + "759599064700838568712381032959192649484625076899225841930548076362021508" + "902214922052806984201835084058693849381549890944546197789302911357651677" + "540623227829831403347327660395223160342282471752818181884430488092132193" + "355086987339586127607367086665237555567580317149010847732009642431878007" + "000879734603290627894355374356444885190719161645514115576193939969076741" + "515640282654366402676009508752394550734155613586793306603174472092444651" + "353236664764973540085196704077110364053815007348689179836404957060618953" + "500508984091382686953509006678332447257871219660441528492484004185093281" + "190896363417573989716659600075948780061916409485433875852065711654107226" + "099628815012314437794400874930194474433078438899570184271000480830501217" + "712356062289507626904285680004771889315808935851559386317665294808903126" + "774702966254511086154895839508779675546413794489596052797520987481383976" + "257859210575628440175934932416214833956535018919681138909184379573470326" + "940634289008780584694035245347939808067427323629788710086717580253156130" + "235606487870925986528841635097252953709111431720488774740553905400942537" + "542411931794417513706468964386151771884986701034153254238591108962471088" + "538580868883777725864856414593426212108664758848926003176234596076950884" + "9149662444156604419552086811989770240.000000"); + + written = LIBC_NAMESPACE::sprintf(big_buff, "%.10Lf", 1e-10L); + ASSERT_STREQ_LEN(written, big_buff, "0.0000000001"); + + written = LIBC_NAMESPACE::sprintf(big_buff, "%.7500Lf", 1e-4900L); + ASSERT_STREQ_LEN( + written, big_buff, + "0." + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000000000000000000000000000000000000000000000000000000000000000000000000" + "000099999999999999999996962764452956071352139203248614920751610856665084" + "549214352477698417183862158583009348897567779527408501588132175167211539" + "462139941448204886585901454195352527238724272760638086779284030512649793" + "039219351187928723378036480041948464946018272171365770411701020666925613" + "422460317465324758217878522666789603627480490870456508256359180089236338" + "765625231186929290294207420828927406735690318849109129700396907705735097" + "663944722727287361650042373203763784830198232253311807069225650324196304" + "532045014970637489181357566354288111205943347410488298480279857453705249" + "232862728556860184412369114663536200895729846877559808001004454634804626" + "541455540260282018142615835686583304903486353937549394736905011798466731" + "536563240053860118551127061960208467764243724656897127545613968909523389" + "577188368809623987105800147797280462974804046545425080530020901531407223" + "191237123282274818236437397994019915368657474589800678444589412286037789" + "891525464936023205313685584525510094270344601331453730179416773626565262" + "480345858564672442896904520146956686863172737711483866766404977719744767" + "834324844875237277613991088218774564658513875732403456058414595576806383" + "115554713240005982141397577420073082470139244845624915873825746771661332" + "098677966580506186966978746832443976821987300902957597498388211921362869" + "017846215557612829071692275292036211064515305528052919611691470945774714" + "135516559501572279732350629089770249554808690411603894492333360300589658" + "470898965370892774715815089075170720164713889237058574941489766701880158" + "060081295483989540170337129032188818293132770882381428397119039835946745" + "549356649433406617266370644136291924838857814675939156677910783740103207" + "523299367093130816446415259371931925208362367989095199399211644084543790" + "110432339056231037520216864358899218874658268610955002763260912337688947" + "822453100821038299301092582962825965939081817836419126254832772002214908" + "085575905761843610944187009818156363893015929300295112598059949496854566" + "638748010633726861510500653821408135845840123073754133549077708843800674" + "328440913743105608636458354618912183716456158809545183074062249922212944" + "249667793845728355381309084891765979111348980470647082269921872595470473" + "719354467594516320911964549508538492057120740224559944452120552719041944" + "961475548547884309626382512432626380881023756568143060204097921571153170" + "723817845809196253498326358439807445210362177680590181657555380795450462" + "223805222580359379367452693270553602179122419370586308101820559214330382" + "570449525088342437216896462077260223998756027453411520977536701491759878" + "422771447006016890777855573925295187921971811871399320142563330377888532" + "179817332113"); +#endif // LIBC_LONG_DOUBLE_IS_X86_FLOAT80 +} + TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) { ForceRoundingMode r(RoundingMode::Nearest); double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); @@ -1865,152 +1876,6 @@ TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) { written = LIBC_NAMESPACE::sprintf(buff, "%E", -nan); ASSERT_STREQ_LEN(written, buff, "-NAN"); - // Length Modifier Tests. - -#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - written = LIBC_NAMESPACE::sprintf(buff, "%.9Le", 1000000000500000000.1L); - ASSERT_STREQ_LEN(written, buff, "1.000000001e+18"); - - written = LIBC_NAMESPACE::sprintf(buff, "%.9Le", 1000000000500000000.0L); - ASSERT_STREQ_LEN(written, buff, "1.000000000e+18"); - - written = LIBC_NAMESPACE::sprintf(buff, "%Le", 0xf.fffffffffffffffp+16380L); - ASSERT_STREQ_LEN(written, buff, "1.189731e+4932"); -#endif - - // TODO: Fix long doubles (needs bigger table or alternate algorithm.) - // Currently the table values are generated, which is very slow. - /* - written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L); - ASSERT_STREQ_LEN(written, buff, - "99999999999999999996693535322073426194986990198284960792713" - "91541752018669482644324418977840117055488.000000"); - - written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1.0L); - ASSERT_STREQ_LEN(written, buff, "1.000000"); - - char big_buff[10000]; - written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e1000L); - ASSERT_STREQ_LEN( - written, big_buff, - "999999999999999999973107317669562353428234857594552594925899449376328728" - "202461036775511405481186963193066642191664822065529414252060696836533522" - "387143501724276282079456797058697369889056407118642873669166717313763499" - "277025985141177344925615052465165938514140943010597323750202561187880136" - "174810574553749194614479541820148407958204853833697063267336294787191005" - "628217462261955103745349844675732989944229689277833828743730290177882029" - "042613704915899149603539993716885598351951895974316347947147507970269673" - "097709017164643598452451201499004104341931127294141495501309305995449742" - "273419524803597130450457553871345958049837885085168840317195672271085085" - "950520957945970913451088104971436093671776829538796532762184174216651692" - "640931965387852083906784898823494867055070322768919156031682291829761007" - "101483799978382119231551218582499361996919560548090784230386907125151658" - "086767207295524036170321059257942621398084478974000973622199163292708506" - "2431457550909271560663602154947063707982236377366647567795879936." - "000000"); - - written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e4900L); - ASSERT_STREQ_LEN( - written, big_buff, - "100000000000000000002708312230690349833224052504078834346502930111959028" - "517260692666637048230414374897655201843766090626319971729765251179632020" - "313912652522792711197087872698264530532442630109549129842736280196919130" - "242615101228133188193853826983121366159061148351354364472807590931218045" - "387490935930967150336231085015126034696883068553581691802388371635128003" - "615577299166097675723780877126495909902479233742826339471026068806070433" - "075629449530819183550315434973800271862658869400009022028602967197463980" - "126881829804282202449930132940824361207087494829502385835258094836304011" - "876250359661206802659650567866176246063987902366800491980400341950657151" - "370854446585517805253310195469184699955519312761482572080479702840420595" - "377369017651259376039167277822106875560385309101650382998482652792335482" - "865443482342801545877390859444282105890147577937366066315975231014810320" - "888482059656248277607763361589359794524314002443575149260630989130103550" - "443177966380769341050735632338583912575890190136462629316287947355057647" - "111088565611192544631519843618778618820046304429723908484879583579178075" - "456701368334212923379389029311286386996015804122917416008806233549005183" - "152461084266176543129004016414959261473645240454289630182591200574019087" - "358223489767381636349719510715487188747217311279465814538495924567014916" - "238565628036285599497236493491668884212847699052761266207598941300449276" - "447201387520841811835583254242213093566548778954711633721122784159793843" - "766802019309395771984693609426401362800013936338891483689127845928572536" - "790651156184721483511507878883282891696900630100211914227950790472211403" - "392549466062537498185758854079775888444518306635752468713312357556380082" - "275500658967283696421824354930077523691855699312544373220921962817907078" - "445538421941800259027487429330768616490865438859612697367766323925013940" - "918384858952407145253573823848733994146335416209309233074165707437420756" - "438833918763109580759409985573826485055208965115587885226774453455112406" - "581351429640282227888764449360534584421929291565334894907337572527922691" - "473242328379737396430908523008687037407295838014450772162091496534584696" - "605157436893236842602956298545594095307060870397506421786236892553632163" - "491468601982681381011940409602294892199042638682530687578982576819839451" - "907594697546439533559153604700750696252355362322662219852740143212566818" - "745528402265116534684566273868361460640280523251242059850044328669692159" - "629900374576027104298177006629276014371540945261309319363704125592775129" - "543526908667388673739382491147471395192495459318806593271282662311169392" - "196897003517840025298267505925987901751541005546610016067658227181318892" - "914686508281007582655667597441346214499847364272258631922040641860333431" - "409838623713258383681350233064164940590695888300919626215847587544298023" - "636416943680102708406086295669759876682046839368574433996997648445207805" - "615784339667691231286807666753972942872019850432610318031627872612657513" - "588188267160616660825719678199868371370527508463011236193719286066916786" - "169956541349011494927225747024994619057884118692213564790598702879596058" - "672338334720925179141906809470606964896245458600635183723159228561689808" - "246141482736625197373238197777325580142168245885279594913851700941789475" - "252421784152262567254611571822468808675893407728003047921107885664474662" - "930921581384003950729114103689170603748380178682003976896397305836815761" - "717676338115866650889936516794601457549097578905329423919798362140648664" - "569177147076571576101649257502509463877402424847669830852345415301684820" - "395813946416649808062227494112874521812750160935760825922220707178083076" - "380203450993589198835885505461509442443773367592842795410339065860781804" - "024975272228687688301824830333940416256885455008512598774611538878683158" - "183931461086893832255176926531299425504132104728730288984598001187854507" - "900417184206801359847651992484444933900133130832052346600926424167009902" - "829803553087005800387704758687923428053612864451456596148162238935900033" - "917094683141205188616000211702577553792389670853917118547527592495253773" - "028135298405566315903922235989614934474805789300370437580494193066066314" - "056627605207631392651010580925826419831250810981343093764403877594495896" - "516881097415880926429607388979497471571321217205535961262051641426436441" - "668989765107456413733909427384182109285933511623871034309722437967253289" - "084018145083721513211807496392673952789642893241520398827805325610653506" - "029060153153064455898648607959013571280930834475689835845791849456112104" - "462337569019001580859906425911782967213265389744605395555069797947978230" - "708108432086217134763779632408473684293543722127232658767439906910370146" - "716836295909075482355827087389127370874842532825987593970846704144140471" - "956027276735614286138656432085771988513977140957180090146798065497158947" - "229765733489703157617307078835099906185890777007500964162371428641176460" - "739074789794941408428328217107759915202650066155868439585510978709442590" - "231934194956788626761834746430104077432547436359522462253411168467463134" - "24896.000000"); -*/ - /* - written = LIBC_NAMESPACE::sprintf(buff, "%La", 0.1L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4"); - #endif - - written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e1000L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "inf"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321"); - #endif - - written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e-1000L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x0p+0"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322"); - #endif - */ - // Min Width Tests. written = LIBC_NAMESPACE::sprintf(buff, "%15e", 1.0); @@ -2428,99 +2293,23 @@ TEST_F(LlvmLibcSPrintfTest, FloatExponentConv) { ASSERT_STREQ_LEN(written, buff, "+1.256e-01 001.256e+03"); } -TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) { +TEST_F(LlvmLibcSPrintfTest, FloatExponentLongDoubleConv) { ForceRoundingMode r(RoundingMode::Nearest); - double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); - double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( - LIBC_NAMESPACE::fputil::Sign::POS, 1) - .get_val(); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.0); - ASSERT_STREQ_LEN(written, buff, "1"); - - written = LIBC_NAMESPACE::sprintf(buff, "%G", -1.0); - ASSERT_STREQ_LEN(written, buff, "-1"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", -1.234567); - ASSERT_STREQ_LEN(written, buff, "-1.23457"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.0); - ASSERT_STREQ_LEN(written, buff, "0"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", -0.0); - ASSERT_STREQ_LEN(written, buff, "-0"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.5); - ASSERT_STREQ_LEN(written, buff, "1.5"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 1e300); - ASSERT_STREQ_LEN(written, buff, "1e+300"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.1); - ASSERT_STREQ_LEN(written, buff, "0.1"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.001); - ASSERT_STREQ_LEN(written, buff, "0.001"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.00001); - ASSERT_STREQ_LEN(written, buff, "1e-05"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.0000001); - ASSERT_STREQ_LEN(written, buff, "1e-07"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.000000001); - ASSERT_STREQ_LEN(written, buff, "1e-09"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.0e-20); - ASSERT_STREQ_LEN(written, buff, "1e-20"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 1234567890123456789.0); - ASSERT_STREQ_LEN(written, buff, "1.23457e+18"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 9999990000000.00); - ASSERT_STREQ_LEN(written, buff, "9.99999e+12"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 9999999000000.00); - ASSERT_STREQ_LEN(written, buff, "1e+13"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0xa.aaaaaaaaaaaaaabp-7); - ASSERT_STREQ_LEN(written, buff, "0.0833333"); - - // Simple Subnormal Tests. - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0x1.0p-1027); - ASSERT_STREQ_LEN(written, buff, "6.95336e-310"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", 0x1.0p-1074); - ASSERT_STREQ_LEN(written, buff, "4.94066e-324"); - - // Inf/Nan Tests. - - written = LIBC_NAMESPACE::sprintf(buff, "%g", inf); - ASSERT_STREQ_LEN(written, buff, "inf"); - - written = LIBC_NAMESPACE::sprintf(buff, "%G", -inf); - ASSERT_STREQ_LEN(written, buff, "-INF"); - - written = LIBC_NAMESPACE::sprintf(buff, "%g", nan); - ASSERT_STREQ_LEN(written, buff, "nan"); - - written = LIBC_NAMESPACE::sprintf(buff, "%G", -nan); - ASSERT_STREQ_LEN(written, buff, "-NAN"); - // Length Modifier Tests. #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + written = LIBC_NAMESPACE::sprintf(buff, "%.9Le", 1000000000500000000.1L); + ASSERT_STREQ_LEN(written, buff, "1.000000001e+18"); - written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xf.fffffffffffffffp+16380L); - ASSERT_STREQ_LEN(written, buff, "1.18973e+4932"); - - written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xa.aaaaaaaaaaaaaabp-7L); - ASSERT_STREQ_LEN(written, buff, "0.0833333"); + written = LIBC_NAMESPACE::sprintf(buff, "%.9Le", 1000000000500000000.0L); + ASSERT_STREQ_LEN(written, buff, "1.000000000e+18"); -#endif // LIBC_LONG_DOUBLE_IS_X86_FLOAT80 + written = LIBC_NAMESPACE::sprintf(buff, "%Le", 0xf.fffffffffffffffp+16380L); + ASSERT_STREQ_LEN(written, buff, "1.189731e+4932"); +#endif - // TODO: Uncomment the below tests after long double support is added + // TODO: Fix long doubles (needs bigger table or alternate algorithm.) + // Currently the table values are generated, which is very slow. /* written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L); ASSERT_STREQ_LEN(written, buff, @@ -2623,34 +2412,87 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) { "231934194956788626761834746430104077432547436359522462253411168467463134" "24896.000000"); */ - /* - written = LIBC_NAMESPACE::sprintf(buff, "%La", 0.1L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4"); - #endif +} - written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e1000L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "inf"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321"); - #endif +TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) { + ForceRoundingMode r(RoundingMode::Nearest); + double inf = LIBC_NAMESPACE::fputil::FPBits::inf().get_val(); + double nan = LIBC_NAMESPACE::fputil::FPBits::build_nan( + LIBC_NAMESPACE::fputil::Sign::POS, 1) + .get_val(); - written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e-1000L); - #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) - ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325"); - #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) - ASSERT_STREQ_LEN(written, buff, "0x0p+0"); - #else // 128 bit long double - ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322"); - #endif - */ + written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.0); + ASSERT_STREQ_LEN(written, buff, "1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%G", -1.0); + ASSERT_STREQ_LEN(written, buff, "-1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", -1.234567); + ASSERT_STREQ_LEN(written, buff, "-1.23457"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.0); + ASSERT_STREQ_LEN(written, buff, "0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", -0.0); + ASSERT_STREQ_LEN(written, buff, "-0"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.5); + ASSERT_STREQ_LEN(written, buff, "1.5"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 1e300); + ASSERT_STREQ_LEN(written, buff, "1e+300"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.1); + ASSERT_STREQ_LEN(written, buff, "0.1"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.001); + ASSERT_STREQ_LEN(written, buff, "0.001"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.00001); + ASSERT_STREQ_LEN(written, buff, "1e-05"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.0000001); + ASSERT_STREQ_LEN(written, buff, "1e-07"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0.000000001); + ASSERT_STREQ_LEN(written, buff, "1e-09"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 1.0e-20); + ASSERT_STREQ_LEN(written, buff, "1e-20"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 1234567890123456789.0); + ASSERT_STREQ_LEN(written, buff, "1.23457e+18"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 9999990000000.00); + ASSERT_STREQ_LEN(written, buff, "9.99999e+12"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 9999999000000.00); + ASSERT_STREQ_LEN(written, buff, "1e+13"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0xa.aaaaaaaaaaaaaabp-7); + ASSERT_STREQ_LEN(written, buff, "0.0833333"); + + // Simple Subnormal Tests. + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0x1.0p-1027); + ASSERT_STREQ_LEN(written, buff, "6.95336e-310"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", 0x1.0p-1074); + ASSERT_STREQ_LEN(written, buff, "4.94066e-324"); + + // Inf/Nan Tests. + + written = LIBC_NAMESPACE::sprintf(buff, "%g", inf); + ASSERT_STREQ_LEN(written, buff, "inf"); + + written = LIBC_NAMESPACE::sprintf(buff, "%G", -inf); + ASSERT_STREQ_LEN(written, buff, "-INF"); + + written = LIBC_NAMESPACE::sprintf(buff, "%g", nan); + ASSERT_STREQ_LEN(written, buff, "nan"); + + written = LIBC_NAMESPACE::sprintf(buff, "%G", -nan); + ASSERT_STREQ_LEN(written, buff, "-NAN"); // Min Width Tests. @@ -3082,6 +2924,157 @@ TEST_F(LlvmLibcSPrintfTest, FloatAutoConv) { ASSERT_STREQ_LEN(written, buff, "+0.126 0001.26e+03"); } +TEST_F(LlvmLibcSPrintfTest, FloatAutoLongDoubleConv) { + ForceRoundingMode r(RoundingMode::Nearest); + + // Length Modifier Tests. + +#if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + + written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xf.fffffffffffffffp+16380L); + ASSERT_STREQ_LEN(written, buff, "1.18973e+4932"); + + written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 0xa.aaaaaaaaaaaaaabp-7L); + ASSERT_STREQ_LEN(written, buff, "0.0833333"); + + written = LIBC_NAMESPACE::sprintf(buff, "%Lg", 9.99999999999e-100L); + ASSERT_STREQ_LEN(written, buff, "1e-99"); + +#endif // LIBC_LONG_DOUBLE_IS_X86_FLOAT80 + + // TODO: Uncomment the below tests after long double support is added + /* + written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1e100L); + ASSERT_STREQ_LEN(written, buff, + "99999999999999999996693535322073426194986990198284960792713" + "91541752018669482644324418977840117055488.000000"); + + written = LIBC_NAMESPACE::sprintf(buff, "%Lf", 1.0L); + ASSERT_STREQ_LEN(written, buff, "1.000000"); + + char big_buff[10000]; + written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e1000L); + ASSERT_STREQ_LEN( + written, big_buff, + "999999999999999999973107317669562353428234857594552594925899449376328728" + "202461036775511405481186963193066642191664822065529414252060696836533522" + "387143501724276282079456797058697369889056407118642873669166717313763499" + "277025985141177344925615052465165938514140943010597323750202561187880136" + "174810574553749194614479541820148407958204853833697063267336294787191005" + "628217462261955103745349844675732989944229689277833828743730290177882029" + "042613704915899149603539993716885598351951895974316347947147507970269673" + "097709017164643598452451201499004104341931127294141495501309305995449742" + "273419524803597130450457553871345958049837885085168840317195672271085085" + "950520957945970913451088104971436093671776829538796532762184174216651692" + "640931965387852083906784898823494867055070322768919156031682291829761007" + "101483799978382119231551218582499361996919560548090784230386907125151658" + "086767207295524036170321059257942621398084478974000973622199163292708506" + "2431457550909271560663602154947063707982236377366647567795879936." + "000000"); + + written = LIBC_NAMESPACE::sprintf(big_buff, "%Lf", 1e4900L); + ASSERT_STREQ_LEN( + written, big_buff, + "100000000000000000002708312230690349833224052504078834346502930111959028" + "517260692666637048230414374897655201843766090626319971729765251179632020" + "313912652522792711197087872698264530532442630109549129842736280196919130" + "242615101228133188193853826983121366159061148351354364472807590931218045" + "387490935930967150336231085015126034696883068553581691802388371635128003" + "615577299166097675723780877126495909902479233742826339471026068806070433" + "075629449530819183550315434973800271862658869400009022028602967197463980" + "126881829804282202449930132940824361207087494829502385835258094836304011" + "876250359661206802659650567866176246063987902366800491980400341950657151" + "370854446585517805253310195469184699955519312761482572080479702840420595" + "377369017651259376039167277822106875560385309101650382998482652792335482" + "865443482342801545877390859444282105890147577937366066315975231014810320" + "888482059656248277607763361589359794524314002443575149260630989130103550" + "443177966380769341050735632338583912575890190136462629316287947355057647" + "111088565611192544631519843618778618820046304429723908484879583579178075" + "456701368334212923379389029311286386996015804122917416008806233549005183" + "152461084266176543129004016414959261473645240454289630182591200574019087" + "358223489767381636349719510715487188747217311279465814538495924567014916" + "238565628036285599497236493491668884212847699052761266207598941300449276" + "447201387520841811835583254242213093566548778954711633721122784159793843" + "766802019309395771984693609426401362800013936338891483689127845928572536" + "790651156184721483511507878883282891696900630100211914227950790472211403" + "392549466062537498185758854079775888444518306635752468713312357556380082" + "275500658967283696421824354930077523691855699312544373220921962817907078" + "445538421941800259027487429330768616490865438859612697367766323925013940" + "918384858952407145253573823848733994146335416209309233074165707437420756" + "438833918763109580759409985573826485055208965115587885226774453455112406" + "581351429640282227888764449360534584421929291565334894907337572527922691" + "473242328379737396430908523008687037407295838014450772162091496534584696" + "605157436893236842602956298545594095307060870397506421786236892553632163" + "491468601982681381011940409602294892199042638682530687578982576819839451" + "907594697546439533559153604700750696252355362322662219852740143212566818" + "745528402265116534684566273868361460640280523251242059850044328669692159" + "629900374576027104298177006629276014371540945261309319363704125592775129" + "543526908667388673739382491147471395192495459318806593271282662311169392" + "196897003517840025298267505925987901751541005546610016067658227181318892" + "914686508281007582655667597441346214499847364272258631922040641860333431" + "409838623713258383681350233064164940590695888300919626215847587544298023" + "636416943680102708406086295669759876682046839368574433996997648445207805" + "615784339667691231286807666753972942872019850432610318031627872612657513" + "588188267160616660825719678199868371370527508463011236193719286066916786" + "169956541349011494927225747024994619057884118692213564790598702879596058" + "672338334720925179141906809470606964896245458600635183723159228561689808" + "246141482736625197373238197777325580142168245885279594913851700941789475" + "252421784152262567254611571822468808675893407728003047921107885664474662" + "930921581384003950729114103689170603748380178682003976896397305836815761" + "717676338115866650889936516794601457549097578905329423919798362140648664" + "569177147076571576101649257502509463877402424847669830852345415301684820" + "395813946416649808062227494112874521812750160935760825922220707178083076" + "380203450993589198835885505461509442443773367592842795410339065860781804" + "024975272228687688301824830333940416256885455008512598774611538878683158" + "183931461086893832255176926531299425504132104728730288984598001187854507" + "900417184206801359847651992484444933900133130832052346600926424167009902" + "829803553087005800387704758687923428053612864451456596148162238935900033" + "917094683141205188616000211702577553792389670853917118547527592495253773" + "028135298405566315903922235989614934474805789300370437580494193066066314" + "056627605207631392651010580925826419831250810981343093764403877594495896" + "516881097415880926429607388979497471571321217205535961262051641426436441" + "668989765107456413733909427384182109285933511623871034309722437967253289" + "084018145083721513211807496392673952789642893241520398827805325610653506" + "029060153153064455898648607959013571280930834475689835845791849456112104" + "462337569019001580859906425911782967213265389744605395555069797947978230" + "708108432086217134763779632408473684293543722127232658767439906910370146" + "716836295909075482355827087389127370874842532825987593970846704144140471" + "956027276735614286138656432085771988513977140957180090146798065497158947" + "229765733489703157617307078835099906185890777007500964162371428641176460" + "739074789794941408428328217107759915202650066155868439585510978709442590" + "231934194956788626761834746430104077432547436359522462253411168467463134" + "24896.000000"); +*/ + /* + written = LIBC_NAMESPACE::sprintf(buff, "%La", 0.1L); + #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0xc.ccccccccccccccdp-7"); + #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "0x1.999999999999ap-4"); + #else // 128 bit long double + ASSERT_STREQ_LEN(written, buff, "0x1.999999999999999999999999999ap-4"); + #endif + + written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e1000L); + #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0xf.38db1f9dd3dac05p+3318"); + #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "inf"); + #else // 128 bit long double + ASSERT_STREQ_LEN(written, buff, "0x1.e71b63f3ba7b580af1a52d2a7379p+3321"); + #endif + + written = LIBC_NAMESPACE::sprintf(buff, "%La", 1.0e-1000L); + #if defined(LIBC_LONG_DOUBLE_IS_X86_FLOAT80) + ASSERT_STREQ_LEN(written, buff, "0x8.68a9188a89e1467p-3325"); + #elif defined(LIBC_LONG_DOUBLE_IS_FLOAT64) + ASSERT_STREQ_LEN(written, buff, "0x0p+0"); + #else // 128 bit long double + ASSERT_STREQ_LEN(written, buff, "0x1.0d152311513c28ce202627c06ec2p-3322"); + #endif + */ +} + #endif // LIBC_COPT_PRINTF_DISABLE_FLOAT #ifndef LIBC_COPT_PRINTF_DISABLE_WRITE_INT diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 6fa47c0090b87..0b95494248ccb 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -25,7 +25,6 @@ licenses(["notice"]) PRINTF_COPTS = [ "LIBC_COPT_STDIO_USE_SYSTEM_FILE", - "LIBC_COPT_PRINTF_DISABLE_INDEX_MODE", "LIBC_COPT_PRINTF_DISABLE_WRITE_INT", ] @@ -416,7 +415,6 @@ libc_support_library( "src/__support/ryu_constants.h", "src/__support/ryu_long_double_constants.h", ], - defines = ["LIBC_COPT_FLOAT_TO_STR_USE_MEGA_LONG_DOUBLE_TABLE"], deps = [ ":__support_common", ":__support_cpp_type_traits",