diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -203,10 +203,10 @@ "`3237 `__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","14.0" "`3238 `__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","","" "`3242 `__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","Prague","|Complete|","Clang 14","|format|" -"`3243 `__","``std::format``\ and negative zeroes","Prague","","","|format|" +"`3243 `__","``std::format``\ and negative zeroes","Prague","|Complete|","14.0","|format|" "`3247 `__","``ranges::iter_move``\ should perform ADL-only lookup of ``iter_move``\ ","Prague","","","|ranges|" "`3248 `__","``std::format``\ ``#b``\ , ``#B``\ , ``#o``\ , ``#x``\ , and ``#X``\ presentation types misformat negative numbers","Prague","|Complete|","14.0","|format|" -"`3250 `__","``std::format``\ : ``#``\ (alternate form) for NaN and inf","Prague","","","|format|" +"`3250 `__","``std::format``\ : ``#``\ (alternate form) for NaN and inf","Prague","|Complete|","14.0","|format|" "`3251 `__","Are ``std::format``\ alignment specifiers applied to string arguments?","Prague","","","|format|" "`3252 `__","Parse locale's aware modifiers for commands are not consistent with POSIX spec","Prague","","","|chrono|" "`3254 `__","Strike ``stop_token``\ 's ``operator!=``\ ","Prague","","" diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -129,7 +129,7 @@ "`P1644R0 `__","LWG","Add wait/notify to atomic","Cologne","","" "`P1650R0 `__","LWG","Output std::chrono::days with 'd' suffix","Cologne","","" "`P1651R0 `__","LWG","bind_front should not unwrap reference_wrapper","Cologne","|Complete|","13.0" -"`P1652R1 `__","LWG","Printf corner cases in std::format","Cologne","|In Progress|","" +"`P1652R1 `__","LWG","Printf corner cases in std::format","Cologne","|Complete|","14.0" "`P1661R1 `__","LWG","Remove dedicated precalculated hash lookup interface","Cologne","|Nothing To Do|","" "`P1754R1 `__","LWG","Rename concepts to standard_case for C++20, while we still can","Cologne","|In Progress|","" "","","","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -148,6 +148,7 @@ __format/formatter.h __format/formatter_bool.h __format/formatter_char.h + __format/formatter_floating_point.h __format/formatter_integer.h __format/formatter_integral.h __format/formatter_string.h diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h --- a/libcxx/include/__format/formatter.h +++ b/libcxx/include/__format/formatter.h @@ -60,6 +60,51 @@ } }; +namespace __format_spec { + +_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, + _Flags::_Sign __sign) { + if (__negative) + *__buf++ = '-'; + else + switch (__sign) { + case _Flags::_Sign::__default: + case _Flags::_Sign::__minus: + // No sign added. + break; + case _Flags::_Sign::__plus: + *__buf++ = '+'; + break; + case _Flags::_Sign::__space: + *__buf++ = ' '; + break; + } + + return __buf; +} + +_LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char c) { + switch (c) { + case 'a': + return 'A'; + case 'b': + return 'B'; + case 'c': + return 'C'; + case 'd': + return 'D'; + case 'e': + return 'E'; + case 'f': + return 'F'; + case 'p': + return 'P'; + } + return c; +} + +} // namespace __format_spec + namespace __formatter { /** The character types that formatters are specialized for. */ diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__format/formatter_floating_point.h @@ -0,0 +1,353 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H +#define _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H + +#include <__algorithm/copy.h> +#include <__algorithm/copy_n.h> +#include <__algorithm/find.h> +#include <__algorithm/fill_n.h> +#include <__algorithm/rotate.h> +#include <__algorithm/transform.h> +#include <__concepts/arithmetic.h> +#include <__config> +#include <__debug> +#include <__format/format_error.h> +#include <__format/format_fwd.h> +#include <__format/format_string.h> +#include <__format/formatter.h> +#include <__utility/move.h> +#include <__format/parser_std_format_spec.h> +#include +#include + +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include +#endif + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +// TODO FMT Remove this once we require compilers with proper C++20 support. +// If the compiler has no concepts support, the format header will be disabled. +// Without concepts support enable_if needs to be used and that too much effort +// to support compilers with partial C++20 support. +# if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace __format_spec { + +inline _LIBCPP_HIDE_FROM_ABI char* __insert_radix(char* __first, char* __last, char __exponent) { +# if 0 + for (; __first != __last; ++__first) { + // Found the radix, return. + if (*__first == '.') + return __last; + + // No radix before exponent, insert one + if (*__first == __exponent) { + // XXX can we just break and rotate __last, __last, __last by virtue __first == __last? + *__last++ = '.'; + _VSTD::rotate(__first, __last - 1, __last); + return __last; + } + } + + *__last++ = '.'; + return __last; +# else + for (; __first != __last; ++__first) { + // Found the radix, return. + if (*__first == '.') + return __last; + + // No radix before exponent, insert one + if (*__first == __exponent) + break; + } + + *__last++ = '.'; + _VSTD::rotate(__first, __last - 1, __last); + return __last; + return __last; +# endif +} + +template <__formatter::__char_type _CharT> +class _LIBCPP_TEMPLATE_VIS __formatter_floating_point : public __parser_floating_point<_CharT> { +public: + template + _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) { + + // XXX or can we test this after substitution? + bool __has_precision = this->__has_precision_field(); + + if (this->__width_needs_substitution()) + this->__substitute_width_arg_id(__ctx.arg(this->__width)); + + if (this->__precision_needs_substitution()) + this->__substitute_precision_arg_id(__ctx.arg(this->__precision)); + + // Depending on the std-format-spec string the sign and the value + // might not be outputted together: + // - zero-padding may insert additional '0' characters. + // Therefore the value is processed as a positive value. + // The function @ref __insert_sign will a '-' when the value was negative. + + bool __negative = _VSTD::signbit(__value); + if (__negative) + __value = _VSTD::copysign(__value, +1.0); + + // XXX select a proper buffer size. + char __buffer[80]; + char* __begin = __buffer; + char* __end = __begin + 80; + char* __first = __insert_sign(__begin, __negative, this->__sign); + char* __last; + bool __to_upper = false; + + if (_VSTD::isfinite(__value)) { + char __exponent = 'e'; + switch (this->__type) { + case _Flags::_Type::__default: + __last = _VSTD::to_chars(__first, __end, __value).ptr; + break; + + // Hex-float never uses a 0x prefix. Not even when alternate form has been selected. + case _Flags::_Type::__float_hexadecimal_upper_case: + __to_upper = true; + [[fallthrough]]; + case _Flags::_Type::__float_hexadecimal_lower_case: + __exponent = 'p'; + if (__has_precision) + __last = _VSTD::to_chars(__first, __end, __value, chars_format::hex, this->__precision).ptr; + else + __last = _VSTD::to_chars(__first, __end, __value, chars_format::hex).ptr; + break; + + case _Flags::_Type::__scientific_upper_case: + __to_upper = true; + [[fallthrough]]; + case _Flags::_Type::__scientific_lower_case: + __last = _VSTD::to_chars(__first, __end, __value, chars_format::scientific, this->__precision).ptr; + break; + + case _Flags::_Type::__fixed_upper_case: + __to_upper = true; + [[fallthrough]]; + case _Flags::_Type::__fixed_lower_case: + __last = _VSTD::to_chars(__first, __end, __value, chars_format::fixed, this->__precision).ptr; + break; + + case _Flags::_Type::__general_upper_case: + __to_upper = true; + [[fallthrough]]; + case _Flags::_Type::__general_lower_case: + __last = _VSTD::to_chars(__first, __end, __value, chars_format::general, this->__precision).ptr; + break; + + default: + _LIBCPP_ASSERT(false, "The parser should have validated the type"); + _LIBCPP_UNREACHABLE(); + } + if (this->__alternate_form) + __last = __insert_radix(__first, __last, __exponent); + +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + if (this->__locale_specific_form) { + const auto& __np = use_facet>(__ctx.locale()); + string __grouping = __np.grouping(); + ptrdiff_t __size = __last - __first; + // Writing the grouped form has more overhead than the normal output + // routines. If there will be no separators written the locale-specific + // form is identical to the normal routine. Test whether to grouped form + // is required. + if (!__grouping.empty() && __size > __grouping[0]) { + // Find the integral part of the value. When this part is smaller + // than the first grouping there's no grouping required. + const char* __last_int = + _VSTD::find_if(__first, __last, [__exponent](char __c) { return __c == '.' || __c == __exponent; }); + __size = __last_int - __first; + // XXX Always called just in cast decimal point differs from '.' + // This may mean a lot of overhead just to replace '.' with __np.decimal_point. + return __format_grouping(__ctx.out(), __begin, __first, __last_int, __last, + __determine_grouping(__size, __grouping), __np.thousands_sep(), __np.decimal_point(), + __to_upper); + } + } +# endif + } else { + + // to_char can return inf, infinity, nan, and nan(n-char-sequence). + // The format library requires inf and nan. + // All in one expression to avoid dangling references. + __last = _VSTD::copy_n(&("infnanINFNAN"[6 * (this->__type == _Flags::_Type::__float_hexadecimal_upper_case || + this->__type == _Flags::_Type::__scientific_upper_case || + this->__type == _Flags::_Type::__fixed_upper_case || + this->__type == _Flags::_Type::__general_upper_case) + + 3 * _VSTD::isnan(__value)]), + 3, __first); + + // [format.string.std]/13 + // A zero (0) character preceding the width field pads the field with + // leading zeros (following any indication of sign or base) to the field + // width, except when applied to an infinity or NaN. + if (this->__alignment == _Flags::_Alignment::__default) + this->__alignment = _Flags::_Alignment::__right; + } + + ptrdiff_t __size = __last - __begin; + if (__size >= this->__width) { + if (__to_upper) + return _VSTD::transform(__begin, __last, __ctx.out(), __hex_to_upper); + return _VSTD::copy(__begin, __last, __ctx.out()); + } + + auto __out_it = __ctx.out(); + if (this->__alignment != _Flags::_Alignment::__default) + __first = __begin; + else { + // When here is a sign output it before the padding. Note the __size + // doesn't need any adjustment, regardless whether the sign is written + // here or in __formatter::__write. + if (__first != __begin) + *__out_it++ = *__begin; + // After the sign is written, zero padding is the same a right alignment + // with '0'. + this->__alignment = _Flags::_Alignment::__right; + this->__fill = _CharT('0'); + } + + if (__to_upper) + return __formatter::__write(_VSTD::move(__out_it), __first, __last, __size, __hex_to_upper, this->__width, + this->__fill, this->__alignment); + + return __formatter::__write(_VSTD::move(__out_it), __first, __last, __size, this->__width, this->__fill, + this->__alignment); + } + +private: +# ifndef _LIBCPP_HAS_NO_LOCALIZATION + /** Format's the locale-specific form's groupings. */ + template + _LIBCPP_HIDE_FROM_ABI _OutIt __format_grouping(_OutIt __out_it, const char* __begin, const char* __first, + const char* __last_int, const char* __last, string&& __grouping, + _CharT __sep, _CharT __point, bool __to_upper) { + + // TODO FMT This function duplicates some functionality of the normal + // output routines. Evaluate whether these parts can be efficiently + // combined with the existing routines. + + unsigned __size = (__first - __begin) + // [sign] + (__last - __first) + // data + (__grouping.size() - 1); // number of separator characters + + __formatter::__padding_size_result __padding = {0, 0}; + if (this->__alignment == _Flags::_Alignment::__default) { + // Write [sign]. + __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it)); + + if (this->__width > __size) { + // Write zero padding. + __padding.__before = this->__width - __size; + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), this->__width - __size, _CharT('0')); + } + } else { + if (this->__width > __size) { + // Determine padding and write padding. + __padding = __formatter::__padding_size(__size, this->__width, this->__alignment); + + __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, this->__fill); + } + // Write [sign]. + __out_it = _VSTD::copy(__begin, __first, _VSTD::move(__out_it)); + } + + auto __r = __grouping.rbegin(); + auto __e = __grouping.rend() - 1; + // The output is divided in small groups of numbers to write: + // - A group before the first separator. + // - A separator and a group, repeated for the number of separators. + // - A group after the last separator. + // This loop achieves that process by testing the termination condition + // midway in the loop. + // + // TODO FMT This loop evaluates the loop invariant `this->__type != + // _Flags::_Type::__hexadecimal_upper_case` for every iteration. (This test + // happens in the __write call.) Benchmark whether making two loops and + // hoisting the invariant is worth the effort. + if (__r != __e) + while (true) { + if (__to_upper) { + const char* __l = __first + *__r; + __out_it = _VSTD::transform(__first, __l, _VSTD::move(__out_it), __hex_to_upper); + __first = __l; + } else { + __out_it = _VSTD::copy_n(__first, *__r, _VSTD::move(__out_it)); + __first += *__r; + } + + if (__r == __e) + break; + + ++__r; + *__out_it++ = __sep; + } + else if (__last_int != __last) { + if (__to_upper) + __out_it = _VSTD::transform(__first, __last_int, _VSTD::move(__out_it), __hex_to_upper); + else + __out_it = _VSTD::copy(__first, __last_int, _VSTD::move(__out_it)); + } + + if (__last_int != __last) { + // __last_int points either at the decimal point or the exponent. Since + // the decimal point precedes the exponent only one test is required. + if (*__last_int == '.') { + *__out_it++ = __point; + ++__last_int; + } + + if (__last_int != __last) { + if (__to_upper) + __out_it = _VSTD::transform(__last_int, __last, _VSTD::move(__out_it), __hex_to_upper); + else + __out_it = _VSTD::copy(__last_int, __last, _VSTD::move(__out_it)); + } + } + + return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, this->__fill); + } +# endif // _LIBCPP_HAS_NO_LOCALIZATION +}; + +} //namespace __format_spec + +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_floating_point<_CharT> {}; +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_floating_point<_CharT> {}; +template +struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter + : public __format_spec::__formatter_floating_point<_CharT> {}; + +# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H diff --git a/libcxx/include/__format/formatter_integral.h b/libcxx/include/__format/formatter_integral.h --- a/libcxx/include/__format/formatter_integral.h +++ b/libcxx/include/__format/formatter_integral.h @@ -133,45 +133,6 @@ + 1; // Reserve space for the sign. } -_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, - _Flags::_Sign __sign) { - if (__negative) - *__buf++ = '-'; - else - switch (__sign) { - case _Flags::_Sign::__default: - case _Flags::_Sign::__minus: - // No sign added. - break; - case _Flags::_Sign::__plus: - *__buf++ = '+'; - break; - case _Flags::_Sign::__space: - *__buf++ = ' '; - break; - } - - return __buf; -} - -_LIBCPP_HIDE_FROM_ABI constexpr char __hex_to_upper(char c) { - switch (c) { - case 'a': - return 'A'; - case 'b': - return 'B'; - case 'c': - return 'C'; - case 'd': - return 'D'; - case 'e': - return 'E'; - case 'f': - return 'F'; - } - return c; -} - /** * Determines the required grouping based on the size of the input. * diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -712,7 +712,140 @@ } }; -// TODO FMT Add a parser for floating-point values. +/** + * The parser for the std-format-spec. + * + * This implements the parser for the floating-point types. + * + * See @ref __parser_string. + */ +template +class _LIBCPP_TEMPLATE_VIS __parser_floating_point + : public __parser_width, // provides __width(|as_arg) + public __parser_precision, // provides __precision(|as_arg) + public __parser_fill_align<_CharT>, // provides __fill and uses __flags + public _Flags // provides __flags +{ +public: + using char_type = _CharT; + + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __it = __parse(__parse_ctx); + __handle_alignment(); + __process_display_type(); + return __it; + } +protected: + /** + * The low-level std-format-spec parse function. + * + * @pre __begin points at the beginning of the std-format-spec. This means + * directly after the ':'. + * @pre The std-format-spec parses the entire input, or the first unmatched + * character is a '}'. + * + * @returns The iterator pointing at the last parsed character. + */ + _LIBCPP_HIDE_FROM_ABI constexpr auto __parse(auto& __parse_ctx) + -> decltype(__parse_ctx.begin()) { + auto __begin = __parse_ctx.begin(); + auto __end = __parse_ctx.end(); + if (__begin == __end) + return __begin; + + __begin = __parser_fill_align<_CharT>::__parse(__begin, __end, + static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_sign(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_alternate_form(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_zero_padding(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parser_width::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = __parser_precision::__parse(__begin, __end, __parse_ctx); + if (__begin == __end) + return __begin; + + __begin = + __parse_locale_specific_form(__begin, static_cast<_Flags&>(*this)); + if (__begin == __end) + return __begin; + + __begin = __parse_type(__begin, static_cast<_Flags&>(*this)); + + if (__begin != __end && *__begin != _CharT('}')) + __throw_format_error( + "The format-spec should consume the input or end with a '}'"); + + return __begin; + } + + /** + * XXX duplicated from __handle_integer ... + */ + _LIBCPP_HIDE_FROM_ABI constexpr void __handle_alignment() noexcept { + this->__zero_padding &= this->__alignment == _Flags::_Alignment::__default; + if (!this->__zero_padding && + this->__alignment == _Flags::_Alignment::__default) + this->__alignment = _Flags::_Alignment::__right; + } + + /** Processes the parsed std-format-spec based on the parsed display type. */ + _LIBCPP_HIDE_FROM_ABI constexpr void __process_display_type() { + switch (this->__type) { + case _Flags::_Type::__default: + // When no precision specified then it keeps default since that + // formatting differs from the other types. + if (this->__has_precision_field()) + this->__type = _Flags::_Type::__general_lower_case; + [[fallthrough]]; + + case _Flags::_Type::__float_hexadecimal_lower_case: + case _Flags::_Type::__float_hexadecimal_upper_case: + // Precision specific behavior will be handled later. + break; + case _Flags::_Type::__scientific_lower_case: + case _Flags::_Type::__scientific_upper_case: + case _Flags::_Type::__fixed_lower_case: + case _Flags::_Type::__fixed_upper_case: + case _Flags::_Type::__general_lower_case: + case _Flags::_Type::__general_upper_case: + if (!this->__has_precision_field()) { + this->__precision = 6; + this->__precision_as_arg = false; + } + break; + + default: + __throw_format_error("The format-spec type has a type not supported for " + "a floating-point argument"); + } + } +}; + // TODO FMT Add a parser for pointer values. /** Helper struct returned from @ref __get_string_alignment. */ diff --git a/libcxx/include/format b/libcxx/include/format --- a/libcxx/include/format +++ b/libcxx/include/format @@ -282,6 +282,7 @@ #include <__format/formatter.h> #include <__format/formatter_bool.h> #include <__format/formatter_char.h> +#include <__format/formatter_floating_point.h> #include <__format/formatter_integer.h> #include <__format/formatter_string.h> #include <__format/parser_std_format_spec.h> diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -451,25 +451,26 @@ export * module __format { - module format_arg { private header "__format/format_arg.h" } - module format_args { private header "__format/format_args.h" } + module format_arg { private header "__format/format_arg.h" } + module format_args { private header "__format/format_args.h" } module format_context { private header "__format/format_context.h" export optional export locale } - module format_error { private header "__format/format_error.h" } - module format_fwd { private header "__format/format_fwd.h" } - module format_parse_context { private header "__format/format_parse_context.h" } - module format_string { private header "__format/format_string.h" } - module format_to_n_result { private header "__format/format_to_n_result.h" } - module formatter { private header "__format/formatter.h" } - module formatter_bool { private header "__format/formatter_bool.h" } - module formatter_char { private header "__format/formatter_char.h" } - module formatter_integer { private header "__format/formatter_integer.h" } - module formatter_integral { private header "__format/formatter_integral.h" } - module formatter_string { private header "__format/formatter_string.h" } - module parser_std_format_spec { private header "__format/parser_std_format_spec.h" } + module format_error { private header "__format/format_error.h" } + module format_fwd { private header "__format/format_fwd.h" } + module format_parse_context { private header "__format/format_parse_context.h" } + module format_string { private header "__format/format_string.h" } + module format_to_n_result { private header "__format/format_to_n_result.h" } + module formatter { private header "__format/formatter.h" } + module formatter_bool { private header "__format/formatter_bool.h" } + module formatter_char { private header "__format/formatter_char.h" } + module formatter_floating_point { private header "__format/formatter_floating_point.h" } + module formatter_integer { private header "__format/formatter_integer.h" } + module formatter_integral { private header "__format/formatter_integral.h" } + module formatter_string { private header "__format/formatter_string.h" } + module parser_std_format_spec { private header "__format/parser_std_format_spec.h" } } } module forward_list { diff --git a/libcxx/test/libcxx/diagnostics/detail.headers/format/formatter_floating_point.module.verify.cpp b/libcxx/test/libcxx/diagnostics/detail.headers/format/formatter_floating_point.module.verify.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/detail.headers/format/formatter_floating_point.module.verify.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: modules-build + +// WARNING: This test was generated by 'generate_private_header_tests.py' +// and should not be edited manually. + +// expected-error@*:* {{use of private header from outside its module: '__format/formatter_floating_point.h'}} +#include <__format/formatter_floating_point.h> diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_floating_point.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_floating_point.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_floating_point.pass.cpp @@ -0,0 +1,355 @@ +//===----------------------------------------------------------------------===// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: libcpp-has-no-incomplete-format + +// + +// Tests the parsing of the format string as specified in [format.string.std]. +// It validates whether the std-format-spec is valid for a floating-point type. + +#include +#include +#ifndef _LIBCPP_HAS_NO_LOCALIZATION +# include +#endif + +#include "concepts_precision.h" +#include "test_macros.h" +#include "make_string.h" +#include "test_exception.h" + +#define CSTR(S) MAKE_CSTRING(CharT, S) + +using namespace std::__format_spec; + +template +using Parser = __parser_floating_point; + +template +struct Expected { + CharT fill = CharT(' '); + _Flags::_Alignment alignment = _Flags::_Alignment::__right; + _Flags::_Sign sign = _Flags::_Sign::__default; + bool alternate_form = false; + bool zero_padding = false; + uint32_t width = 0; + bool width_as_arg = false; + uint32_t precision = std::__format::__number_max; + bool precision_as_arg = true; + bool locale_specific_form = false; + _Flags::_Type type = _Flags::_Type::__default; +}; + +template +constexpr void test(Expected expected, size_t size, std::basic_string_view fmt) { + // Initialize parser with sufficient arguments to avoid the parsing to fail + // due to insufficient arguments. + std::basic_format_parse_context parse_ctx(fmt, std::__format::__number_max); + auto begin = parse_ctx.begin(); + auto end = parse_ctx.end(); + Parser parser; + auto it = parser.parse(parse_ctx); + + assert(begin == parse_ctx.begin()); + assert(end == parse_ctx.end()); + + assert(begin + size == it); + assert(parser.__fill == expected.fill); + assert(parser.__alignment == expected.alignment); + assert(parser.__sign == expected.sign); + assert(parser.__alternate_form == expected.alternate_form); + assert(parser.__zero_padding == expected.zero_padding); + assert(parser.__width == expected.width); + assert(parser.__width_as_arg == expected.width_as_arg); + assert(parser.__precision == expected.precision); + assert(parser.__precision_as_arg == expected.precision_as_arg); + assert(parser.__locale_specific_form == expected.locale_specific_form); + assert(parser.__type == expected.type); +} + +template +constexpr void test(Expected expected, size_t size, const CharT* f) { + // The format-spec is valid if completely consumed or terminates at a '}'. + // The valid inputs all end with a '}'. The test is executed twice: + // - first with the terminating '}', + // - second consuming the entire input. + std::basic_string_view fmt{f}; + assert(fmt.back() == CharT('}') && "Pre-condition failure"); + + test(expected, size, fmt); + fmt.remove_suffix(1); + test(expected, size, fmt); +} + +template +constexpr void test() { + Parser parser; + + assert(parser.__fill == CharT(' ')); + assert(parser.__alignment == _Flags::_Alignment::__default); + assert(parser.__sign == _Flags::_Sign::__default); + assert(parser.__alternate_form == false); + assert(parser.__zero_padding == false); + assert(parser.__width == 0); + assert(parser.__width_as_arg == false); + assert(parser.__precision == std::__format::__number_max); + assert(parser.__precision_as_arg == true); + assert(parser.__locale_specific_form == false); + assert(parser.__type == _Flags::_Type::__default); + + // Depending on whether or not a precision is specified the results differ. + // Table 65: Meaning of type options for floating-point types [tab:format.type.float] + + test({}, 0, CSTR("}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 2, CSTR(".0}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__general_lower_case}, 4, CSTR(".{1}}")); + + test({.type = _Flags::_Type::__float_hexadecimal_lower_case}, 1, CSTR("a}")); + test({.type = _Flags::_Type::__float_hexadecimal_upper_case}, 1, CSTR("A}")); + + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__scientific_lower_case}, 1, CSTR("e}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__scientific_lower_case}, 3, CSTR(".0e}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__scientific_lower_case}, 5, CSTR(".{1}e}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__scientific_upper_case}, 1, CSTR("E}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__scientific_upper_case}, 3, CSTR(".0E}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__scientific_upper_case}, 5, CSTR(".{1}E}")); + + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__fixed_lower_case}, 1, CSTR("f}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__fixed_lower_case}, 3, CSTR(".0f}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__fixed_lower_case}, 5, CSTR(".{1}f}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__fixed_upper_case}, 1, CSTR("F}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__fixed_upper_case}, 3, CSTR(".0F}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__fixed_upper_case}, 5, CSTR(".{1}F}")); + + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 1, CSTR("g}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 3, CSTR(".0g}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__general_lower_case}, 5, CSTR(".{1}g}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__general_upper_case}, 1, CSTR("G}")); + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__general_upper_case}, 3, CSTR(".0G}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__general_upper_case}, 5, CSTR(".{1}G}")); + + // *** Align-fill *** + test({.alignment = _Flags::_Alignment::__left}, 1, CSTR("<}")); + test({.alignment = _Flags::_Alignment::__center}, 1, "^}"); + test({.alignment = _Flags::_Alignment::__right}, 1, ">}"); + + test({.fill = CharT('L'), .alignment = _Flags::_Alignment::__left}, 2, CSTR("L<}")); + test({.fill = CharT('#'), .alignment = _Flags::_Alignment::__center}, 2, CSTR("#^}")); + test({.fill = CharT('0'), .alignment = _Flags::_Alignment::__right}, 2, CSTR("0>}")); + + test_exception>("The format-spec fill field contains an invalid character", CSTR("{<")); + test_exception>("The format-spec fill field contains an invalid character", CSTR("}<")); + + // *** Sign *** + test({.sign = _Flags::_Sign::__minus}, 1, CSTR("-}")); + test({.sign = _Flags::_Sign::__plus}, 1, CSTR("+}")); + test({.sign = _Flags::_Sign::__space}, 1, CSTR(" }")); + + // *** Alternate form *** + test({.alternate_form = true}, 1, CSTR("#}")); + + // *** Zero padding *** + // TODO FMT What to do with zero-padding without a width? + // [format.string.std]/13 + // A zero (0) character preceding the width field pads the field with + // leading zeros (following any indication of sign or base) to the field + // width, except when applied to an infinity or NaN. + // Obviously it makes no sense, but should it be allowed or is it a format + // error? + test({.alignment = _Flags::_Alignment::__default, .zero_padding = true}, 1, CSTR("0}")); + test({.alignment = _Flags::_Alignment::__left, .zero_padding = false}, 2, CSTR("<0}")); + test({.alignment = _Flags::_Alignment::__center, .zero_padding = false}, 2, CSTR("^0}")); + test({.alignment = _Flags::_Alignment::__right, .zero_padding = false}, 2, CSTR(">0}")); + + // *** Width *** + test({.width = 0, .width_as_arg = false}, 0, CSTR("}")); + test({.width = 1, .width_as_arg = false}, 1, CSTR("1}")); + test({.width = 10, .width_as_arg = false}, 2, CSTR("10}")); + test({.width = 1000, .width_as_arg = false}, 4, CSTR("1000}")); + test({.width = 1000000, .width_as_arg = false}, 7, CSTR("1000000}")); + + test({.width = 0, .width_as_arg = true}, 2, CSTR("{}}")); + test({.width = 0, .width_as_arg = true}, 3, CSTR("{0}}")); + test({.width = 1, .width_as_arg = true}, 3, CSTR("{1}}")); + + test_exception>("A format-spec width field shouldn't have a leading zero", CSTR("00")); + + static_assert(std::__format::__number_max == 2'147'483'647, "Update the assert and the test."); + test({.width = 2'147'483'647, .width_as_arg = false}, 10, CSTR("2147483647}")); + test_exception>("The numeric value of the format-spec is too large", CSTR("2147483648")); + test_exception>("The numeric value of the format-spec is too large", CSTR("5000000000")); + test_exception>("The numeric value of the format-spec is too large", CSTR("10000000000")); + + test_exception>("End of input while parsing format-spec arg-id", CSTR("{")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR("{0")); + test_exception>("The arg-id of the format-spec starts with an invalid character", CSTR("{a")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR("{1")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR("{9")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR("{9:")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR("{9a")); + static_assert(std::__format::__number_max == 2'147'483'647, "Update the assert and the test."); + // Note the static_assert tests whether the arg-id is valid. + // Therefore the following should be true arg-id < __format::__number_max. + test({.width = 2'147'483'646, .width_as_arg = true}, 12, CSTR("{2147483646}}")); + test_exception>("The numeric value of the format-spec is too large", CSTR("{2147483648}")); + test_exception>("The numeric value of the format-spec is too large", CSTR("{5000000000}")); + test_exception>("The numeric value of the format-spec is too large", CSTR("{10000000000}")); + + // *** Precision *** + test({.precision = 0, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 2, CSTR(".0}")); + test({.precision = 1, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 2, CSTR(".1}")); + test({.precision = 10, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 3, CSTR(".10}")); + test({.precision = 1000, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 5, CSTR(".1000}")); + test({.precision = 1000000, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 8, + CSTR(".1000000}")); + + test({.precision = 0, .precision_as_arg = true, .type = _Flags::_Type::__general_lower_case}, 3, CSTR(".{}}")); + test({.precision = 0, .precision_as_arg = true, .type = _Flags::_Type::__general_lower_case}, 4, CSTR(".{0}}")); + test({.precision = 1, .precision_as_arg = true, .type = _Flags::_Type::__general_lower_case}, 4, CSTR(".{1}}")); + + test_exception>("A format-spec precision field shouldn't have a leading zero", CSTR(".00")); + test_exception>("A format-spec precision field shouldn't have a leading zero", CSTR(".01")); + test_exception>("The format-spec precision field doesn't contain a value or arg-id", CSTR(".a")); + test_exception>("The format-spec precision field doesn't contain a value or arg-id", CSTR(".:")); + + static_assert(std::__format::__number_max == 2'147'483'647, "Update the assert and the test."); + test({.precision = 2'147'483'647, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 11, + CSTR(".2147483647}")); + test_exception>("The numeric value of the format-spec is too large", CSTR(".2147483648")); + test_exception>("The numeric value of the format-spec is too large", CSTR(".5000000000")); + test_exception>("The numeric value of the format-spec is too large", CSTR(".10000000000")); + + test_exception>("End of input while parsing format-spec arg-id", CSTR(".{")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR(".{0")); + test_exception>("The arg-id of the format-spec starts with an invalid character", CSTR(".{a")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR(".{1")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR(".{9")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR(".{9:")); + test_exception>("A format-spec arg-id should terminate at a '}'", CSTR(".{9a")); + + static_assert(std::__format::__number_max == 2'147'483'647, "Update the assert and the test."); + // Note the static_assert tests whether the arg-id is valid. + // Therefore the following should be true arg-id < __format::__number_max. + test({.precision = 2'147'483'646, .precision_as_arg = true, .type = _Flags::_Type::__general_lower_case}, 13, + CSTR(".{2147483646}}")); + test_exception>("The numeric value of the format-spec is too large", CSTR(".{2147483648}")); + test_exception>("The numeric value of the format-spec is too large", CSTR(".{5000000000}")); + test_exception>("The numeric value of the format-spec is too large", CSTR(".{10000000000}")); + + // *** Width & Precision *** + test({.width = 1, + .width_as_arg = false, + .precision = 0, + .precision_as_arg = false, + .type = _Flags::_Type::__general_lower_case}, + 3, CSTR("1.0}")); + test({.width = 0, + .width_as_arg = true, + .precision = 1, + .precision_as_arg = true, + .type = _Flags::_Type::__general_lower_case}, + 5, CSTR("{}.{}}")); + test({.width = 10, + .width_as_arg = true, + .precision = 9, + .precision_as_arg = true, + .type = _Flags::_Type::__general_lower_case}, + 8, CSTR("{10}.{9}}")); + + // *** Locale-specific form *** + test({.locale_specific_form = true}, 1, CSTR("L}")); + + // *** Type *** + { + const char* unsuported_type = "The format-spec type has a type not supported for a floating-point argument"; + const char* not_a_type = "The format-spec should consume the input or end with a '}'"; + + test({.type = _Flags::_Type::__float_hexadecimal_upper_case}, 1, CSTR("A}")); + test_exception>(unsuported_type, CSTR("B}")); + test_exception>(not_a_type, CSTR("C}")); + test_exception>(not_a_type, CSTR("D}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__scientific_upper_case}, 1, CSTR("E}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__fixed_upper_case}, 1, CSTR("F}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__general_upper_case}, 1, CSTR("G}")); + test_exception>(not_a_type, CSTR("H}")); + test_exception>(not_a_type, CSTR("I}")); + test_exception>(not_a_type, CSTR("J}")); + test_exception>(not_a_type, CSTR("K}")); + test({.locale_specific_form = true}, 1, CSTR("L}")); + test_exception>(not_a_type, CSTR("M}")); + test_exception>(not_a_type, CSTR("N}")); + test_exception>(not_a_type, CSTR("O}")); + test_exception>(not_a_type, CSTR("P}")); + test_exception>(not_a_type, CSTR("Q}")); + test_exception>(not_a_type, CSTR("R}")); + test_exception>(not_a_type, CSTR("S}")); + test_exception>(not_a_type, CSTR("T}")); + test_exception>(not_a_type, CSTR("U}")); + test_exception>(not_a_type, CSTR("V}")); + test_exception>(not_a_type, CSTR("W}")); + test_exception>(unsuported_type, CSTR("X}")); + test_exception>(not_a_type, CSTR("Y}")); + test_exception>(not_a_type, CSTR("Z}")); + + test({.type = _Flags::_Type::__float_hexadecimal_lower_case}, 1, CSTR("a}")); + test_exception>(unsuported_type, CSTR("b}")); + test_exception>(unsuported_type, CSTR("c}")); + test_exception>(unsuported_type, CSTR("d}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__scientific_lower_case}, 1, CSTR("e}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__fixed_lower_case}, 1, CSTR("f}")); + test({.precision = 6, .precision_as_arg = false, .type = _Flags::_Type::__general_lower_case}, 1, CSTR("g}")); + test_exception>(not_a_type, CSTR("h}")); + test_exception>(not_a_type, CSTR("i}")); + test_exception>(not_a_type, CSTR("j}")); + test_exception>(not_a_type, CSTR("k}")); + test_exception>(not_a_type, CSTR("l}")); + test_exception>(not_a_type, CSTR("m}")); + test_exception>(not_a_type, CSTR("n}")); + test_exception>(unsuported_type, CSTR("o}")); + test_exception>(unsuported_type, CSTR("p}")); + test_exception>(not_a_type, CSTR("q}")); + test_exception>(not_a_type, CSTR("r}")); + test_exception>(unsuported_type, CSTR("s}")); + test_exception>(not_a_type, CSTR("t}")); + test_exception>(not_a_type, CSTR("u}")); + test_exception>(not_a_type, CSTR("v}")); + test_exception>(not_a_type, CSTR("w}")); + test_exception>(unsuported_type, CSTR("x}")); + test_exception>(not_a_type, CSTR("y}")); + test_exception>(not_a_type, CSTR("z}")); + } + // **** General *** + test_exception>("The format-spec should consume the input or end with a '}'", CSTR("ss")); +} + +constexpr bool test() { + test(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); +#endif + + return true; +} + +int main(int, char**) { +#ifndef _WIN32 + // Make sure the parsers match the expectations. The layout of the + // subobjects is chosen to minimize the size required. + static_assert(sizeof(Parser) == 3 * sizeof(uint32_t)); +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + static_assert(sizeof(Parser) == (sizeof(wchar_t) <= 2 ? 3 * sizeof(uint32_t) : 4 * sizeof(uint32_t))); +# endif +#endif + + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/utilities/format/format.formatter/format.context/format.formatter.spec/formatter.floating_point.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.context/format.formatter.spec/formatter.floating_point.pass.cpp --- a/libcxx/test/std/utilities/format/format.formatter/format.context/format.formatter.spec/formatter.floating_point.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formatter/format.context/format.formatter.spec/formatter.floating_point.pass.cpp @@ -8,7 +8,6 @@ // UNSUPPORTED: c++03, c++11, c++14, c++17 // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: libcpp-has-no-incomplete-format -// UNSUPPORTED: LIBCXX-DEBUG-FIXME // @@ -25,11 +24,14 @@ // - double // - long double -// TODO FMT Enable after floating-point support has been enabled -#if 0 #include + +#include #include +#include +#include #include +#include #include #include "test_macros.h" @@ -37,9 +39,8 @@ #define STR(S) MAKE_STRING(CharT, S) -template -void test(StringViewT fmt, ArithmeticT arg) { - using CharT = typename StringViewT::value_type; +template +void test(std::basic_string_view fmt, ArithmeticT arg, std::basic_string expected) { auto parse_ctx = std::basic_format_parse_context(fmt); std::formatter formatter; static_assert(std::semiregular); @@ -51,15 +52,19 @@ auto out = std::back_inserter(result); using FormatCtxT = std::basic_format_context; - auto format_ctx = std::__format_context_create( - out, std::make_format_args(arg)); + auto format_ctx = std::__format_context_create(out, std::make_format_args(arg)); formatter.format(arg, format_ctx); - std::string expected = std::to_string(arg); - assert(result == std::basic_string(expected.begin(), expected.end())); + + if (expected.empty()) { + std::array buffer; + expected.append(buffer.begin(), std::to_chars(buffer.begin(), buffer.end(), arg).ptr); + } + + assert(result == expected); } template -void test_termination_condition(StringT f, ArithmeticT arg) { +void test_termination_condition(StringT f, ArithmeticT arg, StringT expected = {}) { // The format-spec is valid if completely consumed or terminates at a '}'. // The valid inputs all end with a '}'. The test is executed twice: // - first with the terminating '}', @@ -68,9 +73,9 @@ std::basic_string_view fmt{f}; assert(fmt.back() == CharT('}') && "Pre-condition failure"); - test(fmt, arg); + test(fmt, arg, expected); fmt.remove_suffix(1); - test(fmt, arg); + test(fmt, arg, expected); } template @@ -79,29 +84,30 @@ test_termination_condition(STR("}"), A(-std::numeric_limits::max())); test_termination_condition(STR("}"), A(-std::numeric_limits::min())); test_termination_condition(STR("}"), A(-0.0)); + test_termination_condition(STR("}"), A(0.0)); test_termination_condition(STR("}"), A(std::numeric_limits::min())); test_termination_condition(STR("}"), A(std::numeric_limits::max())); if (sizeof(A) > sizeof(float)) { - test_termination_condition(STR("}"), - A(-std::numeric_limits::max())); - test_termination_condition(STR("}"), - A(-std::numeric_limits::min())); + test_termination_condition(STR("}"), A(-std::numeric_limits::max())); + test_termination_condition(STR("}"), A(-std::numeric_limits::min())); test_termination_condition(STR("}"), A(std::numeric_limits::min())); test_termination_condition(STR("}"), A(std::numeric_limits::max())); } if (sizeof(A) > sizeof(double)) { - test_termination_condition(STR("}"), - A(-std::numeric_limits::max())); - test_termination_condition(STR("}"), - A(-std::numeric_limits::min())); - test_termination_condition(STR("}"), - A(std::numeric_limits::min())); - test_termination_condition(STR("}"), - A(std::numeric_limits::max())); + test_termination_condition(STR("}"), A(-std::numeric_limits::max())); + test_termination_condition(STR("}"), A(-std::numeric_limits::min())); + test_termination_condition(STR("}"), A(std::numeric_limits::min())); + test_termination_condition(STR("}"), A(std::numeric_limits::max())); } - // TODO FMT Also test with special floating point values: +/-Inf NaN. + // The results of inf and nan may differ from the result of to_chars. + test_termination_condition(STR("}"), A(-std::numeric_limits::infinity()), STR("-inf")); + test_termination_condition(STR("}"), A(std::numeric_limits::infinity()), STR("inf")); + + A nan = std::numeric_limits::quiet_NaN(); + test_termination_condition(STR("}"), std::copysign(nan, -1.0), STR("-nan")); + test_termination_condition(STR("}"), nan, STR("nan")); } template @@ -119,6 +125,3 @@ return 0; } -#else -int main(int, char**) { return 0; } -#endif diff --git a/libcxx/test/std/utilities/format/format.functions/format_tests.h b/libcxx/test/std/utilities/format/format.functions/format_tests.h --- a/libcxx/test/std/utilities/format/format.functions/format_tests.h +++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h @@ -10,6 +10,8 @@ #include "make_string.h" +#include + // In this file the following template types are used: // TestFunction must be callable as check(expected-result, string-to-format, args-to-format...) // ExceptionTest must be callable as check_exception(expected-exception, string-to-format, args-to-format...) @@ -969,6 +971,1493 @@ fmt, '*'); } +template +void format_test_floating_point_hex_lower_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 1p-2'"), STR("answer is '{:7a}'"), F(0.25)); + check(STR("answer is ' 1p-2'"), STR("answer is '{:>7a}'"), F(0.25)); + check(STR("answer is '1p-2 '"), STR("answer is '{:<7a}'"), F(0.25)); + check(STR("answer is ' 1p-2 '"), STR("answer is '{:^7a}'"), F(0.25)); + + check(STR("answer is '---1p-3'"), STR("answer is '{:->7a}'"), F(125e-3)); + check(STR("answer is '1p-3---'"), STR("answer is '{:-<7a}'"), F(125e-3)); + check(STR("answer is '-1p-3--'"), STR("answer is '{:-^7a}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6a}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6a}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6a}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6a}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6a}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6a}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7a}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7a}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7a}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 1p-2'"), STR("answer is '{:>07a}'"), F(0.25)); + check(STR("answer is '1p-2 '"), STR("answer is '{:<07a}'"), F(0.25)); + check(STR("answer is ' 1p-2 '"), STR("answer is '{:^07a}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0p+0'"), STR("answer is '{:a}'"), F(0)); + check(STR("answer is '0p+0'"), STR("answer is '{:-a}'"), F(0)); + check(STR("answer is '+0p+0'"), STR("answer is '{:+a}'"), F(0)); + check(STR("answer is ' 0p+0'"), STR("answer is '{: a}'"), F(0)); + + check(STR("answer is '-0p+0'"), STR("answer is '{:a}'"), F(-0.)); + check(STR("answer is '-0p+0'"), STR("answer is '{:-a}'"), F(-0.)); + check(STR("answer is '-0p+0'"), STR("answer is '{:+a}'"), F(-0.)); + check(STR("answer is '-0p+0'"), STR("answer is '{: a}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:a}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-a}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: a}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:a}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-a}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+a}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: a}'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:a}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-a}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+a}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: a}'"), nan_neg); + + // *** alternate form *** + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0p+0'"), STR("answer is '{:a}'"), F(0)); + check(STR("answer is '0.p+0'"), STR("answer is '{:#a}'"), F(0)); + check(STR("answer is '1.4p+1'"), STR("answer is '{:#a}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#a}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#a}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#a}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '1p-5'"), STR("answer is '{:04a}'"), 0.03125); + check(STR("answer is '+1p-5'"), STR("answer is '{:+05a}'"), 0.03125); + check(STR("answer is '+01p-5'"), STR("answer is '{:+06a}'"), 0.03125); + + check(STR("answer is '0001p-5'"), STR("answer is '{:07a}'"), 0.03125); + check(STR("answer is '0001p-5'"), STR("answer is '{:-07a}'"), 0.03125); + check(STR("answer is '+001p-5'"), STR("answer is '{:+07a}'"), 0.03125); + check(STR("answer is ' 001p-5'"), STR("answer is '{: 07a}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010a}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010a}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010a}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010a}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010a}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010a}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010a}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010a}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010a}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010a}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010a}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010a}'"), nan_neg); + + // *** precision *** + // See format_test_floating_point_hex_lower_case_precision + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_hex_upper_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 1P-2'"), STR("answer is '{:7A}'"), F(0.25)); + check(STR("answer is ' 1P-2'"), STR("answer is '{:>7A}'"), F(0.25)); + check(STR("answer is '1P-2 '"), STR("answer is '{:<7A}'"), F(0.25)); + check(STR("answer is ' 1P-2 '"), STR("answer is '{:^7A}'"), F(0.25)); + + check(STR("answer is '---1P-3'"), STR("answer is '{:->7A}'"), F(125e-3)); + check(STR("answer is '1P-3---'"), STR("answer is '{:-<7A}'"), F(125e-3)); + check(STR("answer is '-1P-3--'"), STR("answer is '{:-^7A}'"), F(125e-3)); + + check(STR("answer is '***INF'"), STR("answer is '{:*>6A}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF***'"), STR("answer is '{:*<6A}'"), std::numeric_limits::infinity()); + check(STR("answer is '*INF**'"), STR("answer is '{:*^6A}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-INF'"), STR("answer is '{:#>7A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF###'"), STR("answer is '{:#<7A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-INF##'"), STR("answer is '{:#^7A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^NAN'"), STR("answer is '{:^>6A}'"), nan_pos); + check(STR("answer is 'NAN^^^'"), STR("answer is '{:^<6A}'"), nan_pos); + check(STR("answer is '^NAN^^'"), STR("answer is '{:^^6A}'"), nan_pos); + + check(STR("answer is '000-NAN'"), STR("answer is '{:0>7A}'"), nan_neg); + check(STR("answer is '-NAN000'"), STR("answer is '{:0<7A}'"), nan_neg); + check(STR("answer is '0-NAN00'"), STR("answer is '{:0^7A}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 1P-2'"), STR("answer is '{:>07A}'"), F(0.25)); + check(STR("answer is '1P-2 '"), STR("answer is '{:<07A}'"), F(0.25)); + check(STR("answer is ' 1P-2 '"), STR("answer is '{:^07A}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0P+0'"), STR("answer is '{:A}'"), F(0)); + check(STR("answer is '0P+0'"), STR("answer is '{:-A}'"), F(0)); + check(STR("answer is '+0P+0'"), STR("answer is '{:+A}'"), F(0)); + check(STR("answer is ' 0P+0'"), STR("answer is '{: A}'"), F(0)); + + check(STR("answer is '-0P+0'"), STR("answer is '{:A}'"), F(-0.)); + check(STR("answer is '-0P+0'"), STR("answer is '{:-A}'"), F(-0.)); + check(STR("answer is '-0P+0'"), STR("answer is '{:+A}'"), F(-0.)); + check(STR("answer is '-0P+0'"), STR("answer is '{: A}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point INFinity and NaN. + check(STR("answer is 'INF'"), STR("answer is '{:A}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF'"), STR("answer is '{:-A}'"), std::numeric_limits::infinity()); + check(STR("answer is '+INF'"), STR("answer is '{:+A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: A}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-INF'"), STR("answer is '{:A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:-A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:+A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{: A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:A}'"), nan_pos); + check(STR("answer is 'NAN'"), STR("answer is '{:-A}'"), nan_pos); + check(STR("answer is '+NAN'"), STR("answer is '{:+A}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: A}'"), nan_pos); + + check(STR("answer is '-NAN'"), STR("answer is '{:A}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:-A}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:+A}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{: A}'"), nan_neg); + + // *** alternate form *** + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0P+0'"), STR("answer is '{:A}'"), F(0)); + check(STR("answer is '0.P+0'"), STR("answer is '{:#A}'"), F(0)); + check(STR("answer is '1.4P+1'"), STR("answer is '{:#A}'"), F(2.5)); + + check(STR("answer is 'INF'"), STR("answer is '{:#A}'"), std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:#A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:#A}'"), nan_pos); + check(STR("answer is '-NAN'"), STR("answer is '{:#A}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '1P-5'"), STR("answer is '{:04A}'"), 0.03125); + check(STR("answer is '+1P-5'"), STR("answer is '{:+05A}'"), 0.03125); + check(STR("answer is '+01P-5'"), STR("answer is '{:+06A}'"), 0.03125); + + check(STR("answer is '0001P-5'"), STR("answer is '{:07A}'"), 0.03125); + check(STR("answer is '0001P-5'"), STR("answer is '{:-07A}'"), 0.03125); + check(STR("answer is '+001P-5'"), STR("answer is '{:+07A}'"), 0.03125); + check(STR("answer is ' 001P-5'"), STR("answer is '{: 07A}'"), 0.03125); + + check(STR("answer is ' INF'"), STR("answer is '{:010A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{:-010A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +INF'"), STR("answer is '{:+010A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: 010A}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -INF'"), STR("answer is '{:010A}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:-010A}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:+010A}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{: 010A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' NAN'"), STR("answer is '{:010A}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{:-010A}'"), nan_pos); + check(STR("answer is ' +NAN'"), STR("answer is '{:+010A}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: 010A}'"), nan_pos); + + check(STR("answer is ' -NAN'"), STR("answer is '{:010A}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:-010A}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:+010A}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{: 010A}'"), nan_neg); + + // *** precision *** + // See format_test_floating_point_hex_upper_case_precision + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_hex_lower_case_precision(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 1.000000p-2'"), STR("answer is '{:14.6a}'"), F(0.25)); + check(STR("answer is ' 1.000000p-2'"), STR("answer is '{:>14.6a}'"), F(0.25)); + check(STR("answer is '1.000000p-2 '"), STR("answer is '{:<14.6a}'"), F(0.25)); + check(STR("answer is ' 1.000000p-2 '"), STR("answer is '{:^14.6a}'"), F(0.25)); + + check(STR("answer is '---1.000000p-3'"), STR("answer is '{:->14.6a}'"), F(125e-3)); + check(STR("answer is '1.000000p-3---'"), STR("answer is '{:-<14.6a}'"), F(125e-3)); + check(STR("answer is '-1.000000p-3--'"), STR("answer is '{:-^14.6a}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6.6a}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7.6a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6.6a}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6.6a}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6.6a}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7.6a}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7.6a}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7.6a}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 1.000000p-2'"), STR("answer is '{:>014.6a}'"), F(0.25)); + check(STR("answer is '1.000000p-2 '"), STR("answer is '{:<014.6a}'"), F(0.25)); + check(STR("answer is ' 1.000000p-2 '"), STR("answer is '{:^014.6a}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0.000000p+0'"), STR("answer is '{:.6a}'"), F(0)); + check(STR("answer is '0.000000p+0'"), STR("answer is '{:-.6a}'"), F(0)); + check(STR("answer is '+0.000000p+0'"), STR("answer is '{:+.6a}'"), F(0)); + check(STR("answer is ' 0.000000p+0'"), STR("answer is '{: .6a}'"), F(0)); + + check(STR("answer is '-0.000000p+0'"), STR("answer is '{:.6a}'"), F(-0.)); + check(STR("answer is '-0.000000p+0'"), STR("answer is '{:-.6a}'"), F(-0.)); + check(STR("answer is '-0.000000p+0'"), STR("answer is '{:+.6a}'"), F(-0.)); + check(STR("answer is '-0.000000p+0'"), STR("answer is '{: .6a}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: .6a}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: .6a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:.6a}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-.6a}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+.6a}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: .6a}'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:.6a}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-.6a}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+.6a}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: .6a}'"), nan_neg); + + // *** alternate form *** + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0p+0'"), STR("answer is '{:.0a}'"), F(0)); + check(STR("answer is '0.p+0'"), STR("answer is '{:#.0a}'"), F(0)); + check(STR("answer is '1.400000p+1'"), STR("answer is '{:#.6a}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#.6a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#.6a}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#.6a}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '1.000000p-5'"), STR("answer is '{:011.6a}'"), 0.03125); + check(STR("answer is '+1.000000p-5'"), STR("answer is '{:+012.6a}'"), 0.03125); + check(STR("answer is '+01.000000p-5'"), STR("answer is '{:+013.6a}'"), 0.03125); + + check(STR("answer is '0001.000000p-5'"), STR("answer is '{:014.6a}'"), 0.03125); + check(STR("answer is '0001.000000p-5'"), STR("answer is '{:-014.6a}'"), 0.03125); + check(STR("answer is '+001.000000p-5'"), STR("answer is '{:+014.6a}'"), 0.03125); + check(STR("answer is ' 001.000000p-5'"), STR("answer is '{: 014.6a}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010.6a}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010.6a}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010.6a}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010.6a}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010.6a}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010.6a}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010.6a}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010.6a}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010.6a}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010.6a}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010.6a}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010.6a}'"), nan_neg); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_hex_upper_case_precision(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 1.000000P-2'"), STR("answer is '{:14.6A}'"), F(0.25)); + check(STR("answer is ' 1.000000P-2'"), STR("answer is '{:>14.6A}'"), F(0.25)); + check(STR("answer is '1.000000P-2 '"), STR("answer is '{:<14.6A}'"), F(0.25)); + check(STR("answer is ' 1.000000P-2 '"), STR("answer is '{:^14.6A}'"), F(0.25)); + + check(STR("answer is '---1.000000P-3'"), STR("answer is '{:->14.6A}'"), F(125e-3)); + check(STR("answer is '1.000000P-3---'"), STR("answer is '{:-<14.6A}'"), F(125e-3)); + check(STR("answer is '-1.000000P-3--'"), STR("answer is '{:-^14.6A}'"), F(125e-3)); + + check(STR("answer is '***INF'"), STR("answer is '{:*>6.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF***'"), STR("answer is '{:*<6.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is '*INF**'"), STR("answer is '{:*^6.6A}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-INF'"), STR("answer is '{:#>7.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF###'"), STR("answer is '{:#<7.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-INF##'"), STR("answer is '{:#^7.6A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^NAN'"), STR("answer is '{:^>6.6A}'"), nan_pos); + check(STR("answer is 'NAN^^^'"), STR("answer is '{:^<6.6A}'"), nan_pos); + check(STR("answer is '^NAN^^'"), STR("answer is '{:^^6.6A}'"), nan_pos); + + check(STR("answer is '000-NAN'"), STR("answer is '{:0>7.6A}'"), nan_neg); + check(STR("answer is '-NAN000'"), STR("answer is '{:0<7.6A}'"), nan_neg); + check(STR("answer is '0-NAN00'"), STR("answer is '{:0^7.6A}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 1.000000P-2'"), STR("answer is '{:>014.6A}'"), F(0.25)); + check(STR("answer is '1.000000P-2 '"), STR("answer is '{:<014.6A}'"), F(0.25)); + check(STR("answer is ' 1.000000P-2 '"), STR("answer is '{:^014.6A}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0.000000P+0'"), STR("answer is '{:.6A}'"), F(0)); + check(STR("answer is '0.000000P+0'"), STR("answer is '{:-.6A}'"), F(0)); + check(STR("answer is '+0.000000P+0'"), STR("answer is '{:+.6A}'"), F(0)); + check(STR("answer is ' 0.000000P+0'"), STR("answer is '{: .6A}'"), F(0)); + + check(STR("answer is '-0.000000P+0'"), STR("answer is '{:.6A}'"), F(-0.)); + check(STR("answer is '-0.000000P+0'"), STR("answer is '{:-.6A}'"), F(-0.)); + check(STR("answer is '-0.000000P+0'"), STR("answer is '{:+.6A}'"), F(-0.)); + check(STR("answer is '-0.000000P+0'"), STR("answer is '{: .6A}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point INFinity and NaN. + check(STR("answer is 'INF'"), STR("answer is '{:.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF'"), STR("answer is '{:-.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is '+INF'"), STR("answer is '{:+.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: .6A}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-INF'"), STR("answer is '{:.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:-.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:+.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{: .6A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:.6A}'"), nan_pos); + check(STR("answer is 'NAN'"), STR("answer is '{:-.6A}'"), nan_pos); + check(STR("answer is '+NAN'"), STR("answer is '{:+.6A}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: .6A}'"), nan_pos); + + check(STR("answer is '-NAN'"), STR("answer is '{:.6A}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:-.6A}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:+.6A}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{: .6A}'"), nan_neg); + + // *** alternate form *** + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0P+0'"), STR("answer is '{:.0A}'"), F(0)); + check(STR("answer is '0.P+0'"), STR("answer is '{:#.0A}'"), F(0)); + check(STR("answer is '1.400000P+1'"), STR("answer is '{:#.6A}'"), F(2.5)); + + check(STR("answer is 'INF'"), STR("answer is '{:#.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:#.6A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:#.6A}'"), nan_pos); + check(STR("answer is '-NAN'"), STR("answer is '{:#.6A}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '1.000000P-5'"), STR("answer is '{:011.6A}'"), 0.03125); + check(STR("answer is '+1.000000P-5'"), STR("answer is '{:+012.6A}'"), 0.03125); + check(STR("answer is '+01.000000P-5'"), STR("answer is '{:+013.6A}'"), 0.03125); + + check(STR("answer is '0001.000000P-5'"), STR("answer is '{:014.6A}'"), 0.03125); + check(STR("answer is '0001.000000P-5'"), STR("answer is '{:-014.6A}'"), 0.03125); + check(STR("answer is '+001.000000P-5'"), STR("answer is '{:+014.6A}'"), 0.03125); + check(STR("answer is ' 001.000000P-5'"), STR("answer is '{: 014.6A}'"), 0.03125); + + check(STR("answer is ' INF'"), STR("answer is '{:010.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{:-010.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +INF'"), STR("answer is '{:+010.6A}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: 010.6A}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -INF'"), STR("answer is '{:010.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:-010.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:+010.6A}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{: 010.6A}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' NAN'"), STR("answer is '{:010.6A}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{:-010.6A}'"), nan_pos); + check(STR("answer is ' +NAN'"), STR("answer is '{:+010.6A}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: 010.6A}'"), nan_pos); + + check(STR("answer is ' -NAN'"), STR("answer is '{:010.6A}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:-010.6A}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:+010.6A}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{: 010.6A}'"), nan_neg); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_scientific_lower_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 2.500000e-01'"), STR("answer is '{:15e}'"), F(0.25)); + check(STR("answer is ' 2.500000e-01'"), STR("answer is '{:>15e}'"), F(0.25)); + check(STR("answer is '2.500000e-01 '"), STR("answer is '{:<15e}'"), F(0.25)); + check(STR("answer is ' 2.500000e-01 '"), STR("answer is '{:^15e}'"), F(0.25)); + + check(STR("answer is '---1.250000e-01'"), STR("answer is '{:->15e}'"), F(125e-3)); + check(STR("answer is '1.250000e-01---'"), STR("answer is '{:-<15e}'"), F(125e-3)); + check(STR("answer is '-1.250000e-01--'"), STR("answer is '{:-^15e}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6e}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6e}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6e}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7e}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7e}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7e}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6e}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6e}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6e}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7e}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7e}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7e}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 2.500000e-01'"), STR("answer is '{:>015e}'"), F(0.25)); + check(STR("answer is '2.500000e-01 '"), STR("answer is '{:<015e}'"), F(0.25)); + check(STR("answer is ' 2.500000e-01 '"), STR("answer is '{:^015e}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0.000000e+00'"), STR("answer is '{:e}'"), F(0)); + check(STR("answer is '0.000000e+00'"), STR("answer is '{:-e}'"), F(0)); + check(STR("answer is '+0.000000e+00'"), STR("answer is '{:+e}'"), F(0)); + check(STR("answer is ' 0.000000e+00'"), STR("answer is '{: e}'"), F(0)); + + check(STR("answer is '-0.000000e+00'"), STR("answer is '{:e}'"), F(-0.)); + check(STR("answer is '-0.000000e+00'"), STR("answer is '{:-e}'"), F(-0.)); + check(STR("answer is '-0.000000e+00'"), STR("answer is '{:+e}'"), F(-0.)); + check(STR("answer is '-0.000000e+00'"), STR("answer is '{: e}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:e}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-e}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+e}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: e}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:e}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-e}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+e}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: e}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:e}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-e}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+e}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: e}'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:e}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-e}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+e}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: e}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0e+00'"), STR("answer is '{:.0e}'"), F(0)); + check(STR("answer is '0.e+00'"), STR("answer is '{:#.0e}'"), F(0)); + + check(STR("answer is '0.000000e+00'"), STR("answer is '{:#e}'"), F(0)); + check(STR("answer is '2.500000e+00'"), STR("answer is '{:#e}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#e}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#e}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#e}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#e}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '3.125000e-02'"), STR("answer is '{:07e}'"), 0.03125); + check(STR("answer is '+3.125000e-02'"), STR("answer is '{:+07e}'"), 0.03125); + check(STR("answer is '+3.125000e-02'"), STR("answer is '{:+08e}'"), 0.03125); + check(STR("answer is '+3.125000e-02'"), STR("answer is '{:+09e}'"), 0.03125); + + check(STR("answer is '003.125000e-02'"), STR("answer is '{:014e}'"), 0.03125); + check(STR("answer is '003.125000e-02'"), STR("answer is '{:-014e}'"), 0.03125); + check(STR("answer is '+03.125000e-02'"), STR("answer is '{:+014e}'"), 0.03125); + check(STR("answer is ' 03.125000e-02'"), STR("answer is '{: 014e}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010e}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010e}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010e}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010e}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010e}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010e}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010e}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010e}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010e}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010e}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010e}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010e}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010e}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010e}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010e}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010e}'"), nan_neg); + + // *** precision *** + check(STR("answer is '3e-02'"), STR("answer is '{:.0e}'"), 0.03125); + check(STR("answer is '3.1e-02'"), STR("answer is '{:.1e}'"), 0.03125); + check(STR("answer is '3.125e-02'"), STR("answer is '{:.3e}'"), 0.03125); + check(STR("answer is '3.1250000000e-02'"), STR("answer is '{:.10e}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_scientific_upper_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 2.500000E-01'"), STR("answer is '{:15E}'"), F(0.25)); + check(STR("answer is ' 2.500000E-01'"), STR("answer is '{:>15E}'"), F(0.25)); + check(STR("answer is '2.500000E-01 '"), STR("answer is '{:<15E}'"), F(0.25)); + check(STR("answer is ' 2.500000E-01 '"), STR("answer is '{:^15E}'"), F(0.25)); + + check(STR("answer is '---1.250000E-01'"), STR("answer is '{:->15E}'"), F(125e-3)); + check(STR("answer is '1.250000E-01---'"), STR("answer is '{:-<15E}'"), F(125e-3)); + check(STR("answer is '-1.250000E-01--'"), STR("answer is '{:-^15E}'"), F(125e-3)); + + check(STR("answer is '***INF'"), STR("answer is '{:*>6E}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF***'"), STR("answer is '{:*<6E}'"), std::numeric_limits::infinity()); + check(STR("answer is '*INF**'"), STR("answer is '{:*^6E}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-INF'"), STR("answer is '{:#>7E}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF###'"), STR("answer is '{:#<7E}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-INF##'"), STR("answer is '{:#^7E}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^NAN'"), STR("answer is '{:^>6E}'"), nan_pos); + check(STR("answer is 'NAN^^^'"), STR("answer is '{:^<6E}'"), nan_pos); + check(STR("answer is '^NAN^^'"), STR("answer is '{:^^6E}'"), nan_pos); + + check(STR("answer is '000-NAN'"), STR("answer is '{:0>7E}'"), nan_neg); + check(STR("answer is '-NAN000'"), STR("answer is '{:0<7E}'"), nan_neg); + check(STR("answer is '0-NAN00'"), STR("answer is '{:0^7E}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 2.500000E-01'"), STR("answer is '{:>015E}'"), F(0.25)); + check(STR("answer is '2.500000E-01 '"), STR("answer is '{:<015E}'"), F(0.25)); + check(STR("answer is ' 2.500000E-01 '"), STR("answer is '{:^015E}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0.000000E+00'"), STR("answer is '{:E}'"), F(0)); + check(STR("answer is '0.000000E+00'"), STR("answer is '{:-E}'"), F(0)); + check(STR("answer is '+0.000000E+00'"), STR("answer is '{:+E}'"), F(0)); + check(STR("answer is ' 0.000000E+00'"), STR("answer is '{: E}'"), F(0)); + + check(STR("answer is '-0.000000E+00'"), STR("answer is '{:E}'"), F(-0.)); + check(STR("answer is '-0.000000E+00'"), STR("answer is '{:-E}'"), F(-0.)); + check(STR("answer is '-0.000000E+00'"), STR("answer is '{:+E}'"), F(-0.)); + check(STR("answer is '-0.000000E+00'"), STR("answer is '{: E}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'INF'"), STR("answer is '{:E}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF'"), STR("answer is '{:-E}'"), std::numeric_limits::infinity()); + check(STR("answer is '+INF'"), STR("answer is '{:+E}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: E}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-INF'"), STR("answer is '{:E}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:-E}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:+E}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{: E}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:E}'"), nan_pos); + check(STR("answer is 'NAN'"), STR("answer is '{:-E}'"), nan_pos); + check(STR("answer is '+NAN'"), STR("answer is '{:+E}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: E}'"), nan_pos); + + check(STR("answer is '-NAN'"), STR("answer is '{:E}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:-E}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:+E}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{: E}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0E+00'"), STR("answer is '{:.0E}'"), F(0)); + check(STR("answer is '0.E+00'"), STR("answer is '{:#.0E}'"), F(0)); + + check(STR("answer is '0.000000E+00'"), STR("answer is '{:#E}'"), F(0)); + check(STR("answer is '2.500000E+00'"), STR("answer is '{:#E}'"), F(2.5)); + + check(STR("answer is 'INF'"), STR("answer is '{:#E}'"), std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:#E}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:#E}'"), nan_pos); + check(STR("answer is '-NAN'"), STR("answer is '{:#E}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '3.125000E-02'"), STR("answer is '{:07E}'"), 0.03125); + check(STR("answer is '+3.125000E-02'"), STR("answer is '{:+07E}'"), 0.03125); + check(STR("answer is '+3.125000E-02'"), STR("answer is '{:+08E}'"), 0.03125); + check(STR("answer is '+3.125000E-02'"), STR("answer is '{:+09E}'"), 0.03125); + + check(STR("answer is '003.125000E-02'"), STR("answer is '{:014E}'"), 0.03125); + check(STR("answer is '003.125000E-02'"), STR("answer is '{:-014E}'"), 0.03125); + check(STR("answer is '+03.125000E-02'"), STR("answer is '{:+014E}'"), 0.03125); + check(STR("answer is ' 03.125000E-02'"), STR("answer is '{: 014E}'"), 0.03125); + + check(STR("answer is ' INF'"), STR("answer is '{:010E}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{:-010E}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +INF'"), STR("answer is '{:+010E}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: 010E}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -INF'"), STR("answer is '{:010E}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:-010E}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:+010E}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{: 010E}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' NAN'"), STR("answer is '{:010E}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{:-010E}'"), nan_pos); + check(STR("answer is ' +NAN'"), STR("answer is '{:+010E}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: 010E}'"), nan_pos); + + check(STR("answer is ' -NAN'"), STR("answer is '{:010E}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:-010E}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:+010E}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{: 010E}'"), nan_neg); + + // *** precision *** + check(STR("answer is '3E-02'"), STR("answer is '{:.0E}'"), 0.03125); + check(STR("answer is '3.1E-02'"), STR("answer is '{:.1E}'"), 0.03125); + check(STR("answer is '3.125E-02'"), STR("answer is '{:.3E}'"), 0.03125); + check(STR("answer is '3.1250000000E-02'"), STR("answer is '{:.10E}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_fixed_lower_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 0.250000'"), STR("answer is '{:11f}'"), F(0.25)); + check(STR("answer is ' 0.250000'"), STR("answer is '{:>11f}'"), F(0.25)); + check(STR("answer is '0.250000 '"), STR("answer is '{:<11f}'"), F(0.25)); + check(STR("answer is ' 0.250000 '"), STR("answer is '{:^11f}'"), F(0.25)); + + check(STR("answer is '---0.125000'"), STR("answer is '{:->11f}'"), F(125e-3)); + check(STR("answer is '0.125000---'"), STR("answer is '{:-<11f}'"), F(125e-3)); + check(STR("answer is '-0.125000--'"), STR("answer is '{:-^11f}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6f}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6f}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6f}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7f}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7f}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7f}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6f}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6f}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6f}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7f}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7f}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7f}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 0.250000'"), STR("answer is '{:>011f}'"), F(0.25)); + check(STR("answer is '0.250000 '"), STR("answer is '{:<011f}'"), F(0.25)); + check(STR("answer is ' 0.250000 '"), STR("answer is '{:^011f}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0.000000'"), STR("answer is '{:f}'"), F(0)); + check(STR("answer is '0.000000'"), STR("answer is '{:-f}'"), F(0)); + check(STR("answer is '+0.000000'"), STR("answer is '{:+f}'"), F(0)); + check(STR("answer is ' 0.000000'"), STR("answer is '{: f}'"), F(0)); + + check(STR("answer is '-0.000000'"), STR("answer is '{:f}'"), F(-0.)); + check(STR("answer is '-0.000000'"), STR("answer is '{:-f}'"), F(-0.)); + check(STR("answer is '-0.000000'"), STR("answer is '{:+f}'"), F(-0.)); + check(STR("answer is '-0.000000'"), STR("answer is '{: f}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:f}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-f}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+f}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: f}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:f}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-f}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+f}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: f}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:f}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-f}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+f}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: f}'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:f}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-f}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+f}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: f}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0'"), STR("answer is '{:.0f}'"), F(0)); + check(STR("answer is '0.'"), STR("answer is '{:#.0f}'"), F(0)); + + check(STR("answer is '0.000000'"), STR("answer is '{:#f}'"), F(0)); + check(STR("answer is '2.500000'"), STR("answer is '{:#f}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#f}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#f}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#f}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#f}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '0.031250'"), STR("answer is '{:07f}'"), 0.03125); + check(STR("answer is '+0.031250'"), STR("answer is '{:+07f}'"), 0.03125); + check(STR("answer is '+0.031250'"), STR("answer is '{:+08f}'"), 0.03125); + check(STR("answer is '+0.031250'"), STR("answer is '{:+09f}'"), 0.03125); + + check(STR("answer is '000.031250'"), STR("answer is '{:010f}'"), 0.03125); + check(STR("answer is '000.031250'"), STR("answer is '{:-010f}'"), 0.03125); + check(STR("answer is '+00.031250'"), STR("answer is '{:+010f}'"), 0.03125); + check(STR("answer is ' 00.031250'"), STR("answer is '{: 010f}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010f}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010f}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010f}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010f}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010f}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010f}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010f}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010f}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010f}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010f}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010f}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010f}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010f}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010f}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010f}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010f}'"), nan_neg); + + // *** precision *** + check(STR("answer is '0'"), STR("answer is '{:.0f}'"), 0.03125); + check(STR("answer is '0.0'"), STR("answer is '{:.1f}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.5f}'"), 0.03125); + check(STR("answer is '0.0312500000'"), STR("answer is '{:.10f}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_fixed_upper_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 0.250000'"), STR("answer is '{:11F}'"), F(0.25)); + check(STR("answer is ' 0.250000'"), STR("answer is '{:>11F}'"), F(0.25)); + check(STR("answer is '0.250000 '"), STR("answer is '{:<11F}'"), F(0.25)); + check(STR("answer is ' 0.250000 '"), STR("answer is '{:^11F}'"), F(0.25)); + + check(STR("answer is '---0.125000'"), STR("answer is '{:->11F}'"), F(125e-3)); + check(STR("answer is '0.125000---'"), STR("answer is '{:-<11F}'"), F(125e-3)); + check(STR("answer is '-0.125000--'"), STR("answer is '{:-^11F}'"), F(125e-3)); + + check(STR("answer is '***INF'"), STR("answer is '{:*>6F}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF***'"), STR("answer is '{:*<6F}'"), std::numeric_limits::infinity()); + check(STR("answer is '*INF**'"), STR("answer is '{:*^6F}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-INF'"), STR("answer is '{:#>7F}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF###'"), STR("answer is '{:#<7F}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-INF##'"), STR("answer is '{:#^7F}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^NAN'"), STR("answer is '{:^>6F}'"), nan_pos); + check(STR("answer is 'NAN^^^'"), STR("answer is '{:^<6F}'"), nan_pos); + check(STR("answer is '^NAN^^'"), STR("answer is '{:^^6F}'"), nan_pos); + + check(STR("answer is '000-NAN'"), STR("answer is '{:0>7F}'"), nan_neg); + check(STR("answer is '-NAN000'"), STR("answer is '{:0<7F}'"), nan_neg); + check(STR("answer is '0-NAN00'"), STR("answer is '{:0^7F}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 0.250000'"), STR("answer is '{:>011F}'"), F(0.25)); + check(STR("answer is '0.250000 '"), STR("answer is '{:<011F}'"), F(0.25)); + check(STR("answer is ' 0.250000 '"), STR("answer is '{:^011F}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0.000000'"), STR("answer is '{:F}'"), F(0)); + check(STR("answer is '0.000000'"), STR("answer is '{:-F}'"), F(0)); + check(STR("answer is '+0.000000'"), STR("answer is '{:+F}'"), F(0)); + check(STR("answer is ' 0.000000'"), STR("answer is '{: F}'"), F(0)); + + check(STR("answer is '-0.000000'"), STR("answer is '{:F}'"), F(-0.)); + check(STR("answer is '-0.000000'"), STR("answer is '{:-F}'"), F(-0.)); + check(STR("answer is '-0.000000'"), STR("answer is '{:+F}'"), F(-0.)); + check(STR("answer is '-0.000000'"), STR("answer is '{: F}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point INFinity and NaN. + check(STR("answer is 'INF'"), STR("answer is '{:F}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF'"), STR("answer is '{:-F}'"), std::numeric_limits::infinity()); + check(STR("answer is '+INF'"), STR("answer is '{:+F}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: F}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-INF'"), STR("answer is '{:F}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:-F}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:+F}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{: F}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:F}'"), nan_pos); + check(STR("answer is 'NAN'"), STR("answer is '{:-F}'"), nan_pos); + check(STR("answer is '+NAN'"), STR("answer is '{:+F}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: F}'"), nan_pos); + + check(STR("answer is '-NAN'"), STR("answer is '{:F}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:-F}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:+F}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{: F}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0'"), STR("answer is '{:.0F}'"), F(0)); + check(STR("answer is '0.'"), STR("answer is '{:#.0F}'"), F(0)); + + check(STR("answer is '0.000000'"), STR("answer is '{:#F}'"), F(0)); + check(STR("answer is '2.500000'"), STR("answer is '{:#F}'"), F(2.5)); + + check(STR("answer is 'INF'"), STR("answer is '{:#F}'"), std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:#F}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:#F}'"), nan_pos); + check(STR("answer is '-NAN'"), STR("answer is '{:#F}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '0.031250'"), STR("answer is '{:07F}'"), 0.03125); + check(STR("answer is '+0.031250'"), STR("answer is '{:+07F}'"), 0.03125); + check(STR("answer is '+0.031250'"), STR("answer is '{:+08F}'"), 0.03125); + check(STR("answer is '+0.031250'"), STR("answer is '{:+09F}'"), 0.03125); + + check(STR("answer is '000.031250'"), STR("answer is '{:010F}'"), 0.03125); + check(STR("answer is '000.031250'"), STR("answer is '{:-010F}'"), 0.03125); + check(STR("answer is '+00.031250'"), STR("answer is '{:+010F}'"), 0.03125); + check(STR("answer is ' 00.031250'"), STR("answer is '{: 010F}'"), 0.03125); + + check(STR("answer is ' INF'"), STR("answer is '{:010F}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{:-010F}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +INF'"), STR("answer is '{:+010F}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: 010F}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -INF'"), STR("answer is '{:010F}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:-010F}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:+010F}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{: 010F}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' NAN'"), STR("answer is '{:010F}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{:-010F}'"), nan_pos); + check(STR("answer is ' +NAN'"), STR("answer is '{:+010F}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: 010F}'"), nan_pos); + + check(STR("answer is ' -NAN'"), STR("answer is '{:010F}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:-010F}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:+010F}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{: 010F}'"), nan_neg); + + // *** precision *** + check(STR("answer is '0'"), STR("answer is '{:.0F}'"), 0.03125); + check(STR("answer is '0.0'"), STR("answer is '{:.1F}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.5F}'"), 0.03125); + check(STR("answer is '0.0312500000'"), STR("answer is '{:.10F}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_general_lower_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 0.25'"), STR("answer is '{:7g}'"), F(0.25)); + check(STR("answer is ' 0.25'"), STR("answer is '{:>7g}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<7g}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^7g}'"), F(0.25)); + + check(STR("answer is '---0.125'"), STR("answer is '{:->8g}'"), F(125e-3)); + check(STR("answer is '0.125---'"), STR("answer is '{:-<8g}'"), F(125e-3)); + check(STR("answer is '-0.125--'"), STR("answer is '{:-^8g}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6g}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6g}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6g}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7g}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7g}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7g}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6g}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6g}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6g}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7g}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7g}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7g}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 0.25'"), STR("answer is '{:>07g}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<07g}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^07g}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0'"), STR("answer is '{:g}'"), F(0)); + check(STR("answer is '0'"), STR("answer is '{:-g}'"), F(0)); + check(STR("answer is '+0'"), STR("answer is '{:+g}'"), F(0)); + check(STR("answer is ' 0'"), STR("answer is '{: g}'"), F(0)); + + check(STR("answer is '-0'"), STR("answer is '{:g}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:-g}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:+g}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{: g}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:g}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-g}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+g}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: g}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:g}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-g}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+g}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: g}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:g}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-g}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+g}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: g}'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:g}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-g}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+g}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: g}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0'"), STR("answer is '{:.0g}'"), F(0)); + check(STR("answer is '0.'"), STR("answer is '{:#.0g}'"), F(0)); + + check(STR("answer is '0.'"), STR("answer is '{:#g}'"), F(0)); + check(STR("answer is '2.5'"), STR("answer is '{:#g}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#g}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#g}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#g}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#g}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '0.03125'"), STR("answer is '{:06g}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+06g}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+07g}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+08g}'"), 0.03125); + + check(STR("answer is '000.03125'"), STR("answer is '{:09g}'"), 0.03125); + check(STR("answer is '000.03125'"), STR("answer is '{:-09g}'"), 0.03125); + check(STR("answer is '+00.03125'"), STR("answer is '{:+09g}'"), 0.03125); + check(STR("answer is ' 00.03125'"), STR("answer is '{: 09g}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010g}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010g}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010g}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010g}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010g}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010g}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010g}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010g}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010g}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010g}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010g}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010g}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010g}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010g}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010g}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010g}'"), nan_neg); + + // *** precision *** + check(STR("answer is '0.03'"), STR("answer is '{:.0g}'"), 0.03125); + check(STR("answer is '0.03'"), STR("answer is '{:.1g}'"), 0.03125); + check(STR("answer is '0.031'"), STR("answer is '{:.2g}'"), 0.03125); + check(STR("answer is '0.0312'"), STR("answer is '{:.3g}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.4g}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.5g}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.10g}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_general_upper_case(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 0.25'"), STR("answer is '{:7G}'"), F(0.25)); + check(STR("answer is ' 0.25'"), STR("answer is '{:>7G}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<7G}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^7G}'"), F(0.25)); + + check(STR("answer is '---0.125'"), STR("answer is '{:->8G}'"), F(125e-3)); + check(STR("answer is '0.125---'"), STR("answer is '{:-<8G}'"), F(125e-3)); + check(STR("answer is '-0.125--'"), STR("answer is '{:-^8G}'"), F(125e-3)); + + check(STR("answer is '***INF'"), STR("answer is '{:*>6G}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF***'"), STR("answer is '{:*<6G}'"), std::numeric_limits::infinity()); + check(STR("answer is '*INF**'"), STR("answer is '{:*^6G}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-INF'"), STR("answer is '{:#>7G}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF###'"), STR("answer is '{:#<7G}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-INF##'"), STR("answer is '{:#^7G}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^NAN'"), STR("answer is '{:^>6G}'"), nan_pos); + check(STR("answer is 'NAN^^^'"), STR("answer is '{:^<6G}'"), nan_pos); + check(STR("answer is '^NAN^^'"), STR("answer is '{:^^6G}'"), nan_pos); + + check(STR("answer is '000-NAN'"), STR("answer is '{:0>7G}'"), nan_neg); + check(STR("answer is '-NAN000'"), STR("answer is '{:0<7G}'"), nan_neg); + check(STR("answer is '0-NAN00'"), STR("answer is '{:0^7G}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 0.25'"), STR("answer is '{:>07G}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<07G}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^07G}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0'"), STR("answer is '{:G}'"), F(0)); + check(STR("answer is '0'"), STR("answer is '{:-G}'"), F(0)); + check(STR("answer is '+0'"), STR("answer is '{:+G}'"), F(0)); + check(STR("answer is ' 0'"), STR("answer is '{: G}'"), F(0)); + + check(STR("answer is '-0'"), STR("answer is '{:G}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:-G}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:+G}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{: G}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point INFinity and NaN. + check(STR("answer is 'INF'"), STR("answer is '{:G}'"), std::numeric_limits::infinity()); + check(STR("answer is 'INF'"), STR("answer is '{:-G}'"), std::numeric_limits::infinity()); + check(STR("answer is '+INF'"), STR("answer is '{:+G}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: G}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-INF'"), STR("answer is '{:G}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:-G}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:+G}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{: G}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:G}'"), nan_pos); + check(STR("answer is 'NAN'"), STR("answer is '{:-G}'"), nan_pos); + check(STR("answer is '+NAN'"), STR("answer is '{:+G}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: G}'"), nan_pos); + + check(STR("answer is '-NAN'"), STR("answer is '{:G}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:-G}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{:+G}'"), nan_neg); + check(STR("answer is '-NAN'"), STR("answer is '{: G}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0'"), STR("answer is '{:.0G}'"), F(0)); + check(STR("answer is '0.'"), STR("answer is '{:#.0G}'"), F(0)); + + check(STR("answer is '0.'"), STR("answer is '{:#G}'"), F(0)); + check(STR("answer is '2.5'"), STR("answer is '{:#G}'"), F(2.5)); + + check(STR("answer is 'INF'"), STR("answer is '{:#G}'"), std::numeric_limits::infinity()); + check(STR("answer is '-INF'"), STR("answer is '{:#G}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'NAN'"), STR("answer is '{:#G}'"), nan_pos); + check(STR("answer is '-NAN'"), STR("answer is '{:#G}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '0.03125'"), STR("answer is '{:06G}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+06G}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+07G}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+08G}'"), 0.03125); + + check(STR("answer is '000.03125'"), STR("answer is '{:09G}'"), 0.03125); + check(STR("answer is '000.03125'"), STR("answer is '{:-09G}'"), 0.03125); + check(STR("answer is '+00.03125'"), STR("answer is '{:+09G}'"), 0.03125); + check(STR("answer is ' 00.03125'"), STR("answer is '{: 09G}'"), 0.03125); + + check(STR("answer is ' INF'"), STR("answer is '{:010G}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{:-010G}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +INF'"), STR("answer is '{:+010G}'"), std::numeric_limits::infinity()); + check(STR("answer is ' INF'"), STR("answer is '{: 010G}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -INF'"), STR("answer is '{:010G}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:-010G}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{:+010G}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -INF'"), STR("answer is '{: 010G}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' NAN'"), STR("answer is '{:010G}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{:-010G}'"), nan_pos); + check(STR("answer is ' +NAN'"), STR("answer is '{:+010G}'"), nan_pos); + check(STR("answer is ' NAN'"), STR("answer is '{: 010G}'"), nan_pos); + + check(STR("answer is ' -NAN'"), STR("answer is '{:010G}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:-010G}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{:+010G}'"), nan_neg); + check(STR("answer is ' -NAN'"), STR("answer is '{: 010G}'"), nan_neg); + + // *** precision *** + check(STR("answer is '0.03'"), STR("answer is '{:.0G}'"), 0.03125); + check(STR("answer is '0.03'"), STR("answer is '{:.1G}'"), 0.03125); + check(STR("answer is '0.031'"), STR("answer is '{:.2G}'"), 0.03125); + check(STR("answer is '0.0312'"), STR("answer is '{:.3G}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.4G}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.5G}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.10G}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_default(TestFunction check) { + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 0.25'"), STR("answer is '{:7}'"), F(0.25)); + check(STR("answer is ' 0.25'"), STR("answer is '{:>7}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<7}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^7}'"), F(0.25)); + + check(STR("answer is '---0.125'"), STR("answer is '{:->8}'"), F(125e-3)); + check(STR("answer is '0.125---'"), STR("answer is '{:-<8}'"), F(125e-3)); + check(STR("answer is '-0.125--'"), STR("answer is '{:-^8}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 0.25'"), STR("answer is '{:>07}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<07}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^07}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0'"), STR("answer is '{:}'"), F(0)); + check(STR("answer is '0'"), STR("answer is '{:-}'"), F(0)); + check(STR("answer is '+0'"), STR("answer is '{:+}'"), F(0)); + check(STR("answer is ' 0'"), STR("answer is '{: }'"), F(0)); + + check(STR("answer is '-0'"), STR("answer is '{:}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:-}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:+}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{: }'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: }'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: }'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: }'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: }'"), nan_neg); + + // *** alternate form *** + check(STR("answer is '0.'"), STR("answer is '{:#}'"), F(0)); + check(STR("answer is '2.5'"), STR("answer is '{:#}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '0.03125'"), STR("answer is '{:07}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+07}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+08}'"), 0.03125); + check(STR("answer is '+00.03125'"), STR("answer is '{:+09}'"), 0.03125); + + check(STR("answer is '0000.03125'"), STR("answer is '{:010}'"), 0.03125); + check(STR("answer is '0000.03125'"), STR("answer is '{:-010}'"), 0.03125); + check(STR("answer is '+000.03125'"), STR("answer is '{:+010}'"), 0.03125); + check(STR("answer is ' 000.03125'"), STR("answer is '{: 010}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010}'"), nan_neg); + + // *** precision *** + // See format_test_floating_point_default_precision + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point_default_precision(TestFunction check) { + + auto nan_pos = std::numeric_limits::quiet_NaN(); // "nan" + auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan" + + // *** align-fill & width *** + check(STR("answer is ' 0.25'"), STR("answer is '{:7.6}'"), F(0.25)); + check(STR("answer is ' 0.25'"), STR("answer is '{:>7.6}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<7.6}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^7.6}'"), F(0.25)); + + check(STR("answer is '---0.125'"), STR("answer is '{:->8.6}'"), F(125e-3)); + check(STR("answer is '0.125---'"), STR("answer is '{:-<8.6}'"), F(125e-3)); + check(STR("answer is '-0.125--'"), STR("answer is '{:-^8.6}'"), F(125e-3)); + + check(STR("answer is '***inf'"), STR("answer is '{:*>6.6}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf***'"), STR("answer is '{:*<6.6}'"), std::numeric_limits::infinity()); + check(STR("answer is '*inf**'"), STR("answer is '{:*^6.6}'"), std::numeric_limits::infinity()); + + check(STR("answer is '###-inf'"), STR("answer is '{:#>7.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf###'"), STR("answer is '{:#<7.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is '#-inf##'"), STR("answer is '{:#^7.6}'"), -std::numeric_limits::infinity()); + + check(STR("answer is '^^^nan'"), STR("answer is '{:^>6.6}'"), nan_pos); + check(STR("answer is 'nan^^^'"), STR("answer is '{:^<6.6}'"), nan_pos); + check(STR("answer is '^nan^^'"), STR("answer is '{:^^6.6}'"), nan_pos); + + check(STR("answer is '000-nan'"), STR("answer is '{:0>7.6}'"), nan_neg); + check(STR("answer is '-nan000'"), STR("answer is '{:0<7.6}'"), nan_neg); + check(STR("answer is '0-nan00'"), STR("answer is '{:0^7.6}'"), nan_neg); + + // Test whether zero padding is ignored + check(STR("answer is ' 0.25'"), STR("answer is '{:>07.6}'"), F(0.25)); + check(STR("answer is '0.25 '"), STR("answer is '{:<07.6}'"), F(0.25)); + check(STR("answer is ' 0.25 '"), STR("answer is '{:^07.6}'"), F(0.25)); + + // *** Sign *** + check(STR("answer is '0'"), STR("answer is '{:.6}'"), F(0)); + check(STR("answer is '0'"), STR("answer is '{:-.6}'"), F(0)); + check(STR("answer is '+0'"), STR("answer is '{:+.6}'"), F(0)); + check(STR("answer is ' 0'"), STR("answer is '{: .6}'"), F(0)); + + check(STR("answer is '-0'"), STR("answer is '{:.6}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:-.6}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{:+.6}'"), F(-0.)); + check(STR("answer is '-0'"), STR("answer is '{: .6}'"), F(-0.)); + + // [format.string.std]/5 The sign option applies to floating-point infinity and NaN. + check(STR("answer is 'inf'"), STR("answer is '{:.6}'"), std::numeric_limits::infinity()); + check(STR("answer is 'inf'"), STR("answer is '{:-.6}'"), std::numeric_limits::infinity()); + check(STR("answer is '+inf'"), STR("answer is '{:+.6}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: .6}'"), std::numeric_limits::infinity()); + + check(STR("answer is '-inf'"), STR("answer is '{:.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:-.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:+.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{: .6}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:.6}'"), nan_pos); + check(STR("answer is 'nan'"), STR("answer is '{:-.6}'"), nan_pos); + check(STR("answer is '+nan'"), STR("answer is '{:+.6}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: .6}'"), nan_pos); + + check(STR("answer is '-nan'"), STR("answer is '{:.6}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:-.6}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{:+.6}'"), nan_neg); + check(STR("answer is '-nan'"), STR("answer is '{: .6}'"), nan_neg); + + // *** alternate form ** + + // When precission is zero there's no decimal point except when the alternate form is specified. + check(STR("answer is '0'"), STR("answer is '{:.0}'"), F(0)); + check(STR("answer is '0.'"), STR("answer is '{:#.0}'"), F(0)); + + check(STR("answer is '0.'"), STR("answer is '{:#.6}'"), F(0)); + check(STR("answer is '2.5'"), STR("answer is '{:#.6}'"), F(2.5)); + + check(STR("answer is 'inf'"), STR("answer is '{:#.6}'"), std::numeric_limits::infinity()); + check(STR("answer is '-inf'"), STR("answer is '{:#.6}'"), -std::numeric_limits::infinity()); + + check(STR("answer is 'nan'"), STR("answer is '{:#.6}'"), nan_pos); + check(STR("answer is '-nan'"), STR("answer is '{:#.6}'"), nan_neg); + + // *** zero-padding & width *** + check(STR("answer is '0.03125'"), STR("answer is '{:06.6}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+06.6}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+07.6}'"), 0.03125); + check(STR("answer is '+0.03125'"), STR("answer is '{:+08.6}'"), 0.03125); + + check(STR("answer is '000.03125'"), STR("answer is '{:09.6}'"), 0.03125); + check(STR("answer is '000.03125'"), STR("answer is '{:-09.6}'"), 0.03125); + check(STR("answer is '+00.03125'"), STR("answer is '{:+09.6}'"), 0.03125); + check(STR("answer is ' 00.03125'"), STR("answer is '{: 09.6}'"), 0.03125); + + check(STR("answer is ' inf'"), STR("answer is '{:010.6}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{:-010.6}'"), std::numeric_limits::infinity()); + check(STR("answer is ' +inf'"), STR("answer is '{:+010.6}'"), std::numeric_limits::infinity()); + check(STR("answer is ' inf'"), STR("answer is '{: 010.6}'"), std::numeric_limits::infinity()); + + check(STR("answer is ' -inf'"), STR("answer is '{:010.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:-010.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{:+010.6}'"), -std::numeric_limits::infinity()); + check(STR("answer is ' -inf'"), STR("answer is '{: 010.6}'"), -std::numeric_limits::infinity()); + + check(STR("answer is ' nan'"), STR("answer is '{:010.6}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{:-010.6}'"), nan_pos); + check(STR("answer is ' +nan'"), STR("answer is '{:+010.6}'"), nan_pos); + check(STR("answer is ' nan'"), STR("answer is '{: 010.6}'"), nan_pos); + + check(STR("answer is ' -nan'"), STR("answer is '{:010.6}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:-010.6}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{:+010.6}'"), nan_neg); + check(STR("answer is ' -nan'"), STR("answer is '{: 010.6}'"), nan_neg); + + // *** precision *** + check(STR("answer is '0.03'"), STR("answer is '{:.0}'"), 0.03125); + check(STR("answer is '0.03'"), STR("answer is '{:.1}'"), 0.03125); + check(STR("answer is '0.031'"), STR("answer is '{:.2}'"), 0.03125); + check(STR("answer is '0.0312'"), STR("answer is '{:.3}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.4}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.5}'"), 0.03125); + check(STR("answer is '0.03125'"), STR("answer is '{:.10}'"), 0.03125); + + // *** locale-specific form *** + // See locale-specific_form.pass.cpp +} + +template +void format_test_floating_point(TestFunction check, ExceptionTest check_exception) { + format_test_floating_point_hex_lower_case(check); + format_test_floating_point_hex_upper_case(check); + format_test_floating_point_hex_lower_case_precision(check); + format_test_floating_point_hex_upper_case_precision(check); + + format_test_floating_point_scientific_lower_case(check); + format_test_floating_point_scientific_upper_case(check); + + format_test_floating_point_fixed_lower_case(check); + format_test_floating_point_fixed_upper_case(check); + + format_test_floating_point_general_lower_case(check); + format_test_floating_point_general_upper_case(check); + + format_test_floating_point_default(check); + format_test_floating_point_default_precision(check); + + // *** type *** + for (const auto& fmt : invalid_types("aAeEfFgG")) + check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, F(1)); +} + +template +void format_test_floating_point(TestFunction check, ExceptionTest check_exception) { + format_test_floating_point(check, check_exception); + format_test_floating_point(check, check_exception); + format_test_floating_point(check, check_exception); +} + template void format_tests(TestFunction check, ExceptionTest check_exception) { // *** Test escaping *** @@ -1092,12 +2581,10 @@ format_test_unsigned_integer(check, check_exception); // *** Test floating point format argument *** -// TODO FMT Enable after floating-point support has been enabled -#if 0 - check(STR("hello 42.000000"), STR("hello {}"), static_cast(42)); - check(STR("hello 42.000000"), STR("hello {}"), static_cast(42)); - check(STR("hello 42.000000"), STR("hello {}"), static_cast(42)); -#endif + check(STR("hello 42"), STR("hello {}"), static_cast(42)); + check(STR("hello 42"), STR("hello {}"), static_cast(42)); + check(STR("hello 42"), STR("hello {}"), static_cast(42)); + format_test_floating_point(check, check_exception); } #ifndef TEST_HAS_NO_WIDE_CHARACTERS diff --git a/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp b/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp @@ -111,6 +111,7 @@ std::string do_grouping() const override { return "\1\2\3\2\1"; }; char do_thousands_sep() const override { return '_'; } + char do_decimal_point() const override { return '#'; } }; #ifndef TEST_HAS_NO_WIDE_CHARACTERS @@ -121,6 +122,7 @@ std::string do_grouping() const override { return "\1\2\3\2\1"; }; wchar_t do_thousands_sep() const override { return L'_'; } + wchar_t do_decimal_point() const override { return L'#'; } }; #endif @@ -617,10 +619,1726 @@ test(STR("-0X004_A"), loc, STR("{:#08LX}"), -0x4a); } +template +void test_floating_point_hex_lower_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.23456p-3"), STR("{:La}"), F(0x1.23456p-3)); + test(STR("1.23456p-2"), STR("{:La}"), F(0x1.23456p-2)); + test(STR("1.23456p-1"), STR("{:La}"), F(0x1.23456p-1)); + test(STR("1.23456p+0"), STR("{:La}"), F(0x1.23456p0)); + test(STR("1.23456p+1"), STR("{:La}"), F(0x1.23456p+1)); + test(STR("1.23456p+2"), STR("{:La}"), F(0x1.23456p+2)); + test(STR("1.23456p+3"), STR("{:La}"), F(0x1.23456p+3)); + test(STR("1.23456p+20"), STR("{:La}"), F(0x1.23456p+20)); + + std::locale::global(loc); + test(STR("1#23456p-3"), STR("{:La}"), F(0x1.23456p-3)); + test(STR("1#23456p-2"), STR("{:La}"), F(0x1.23456p-2)); + test(STR("1#23456p-1"), STR("{:La}"), F(0x1.23456p-1)); + test(STR("1#23456p+0"), STR("{:La}"), F(0x1.23456p0)); + test(STR("1#23456p+1"), STR("{:La}"), F(0x1.23456p+1)); + test(STR("1#23456p+2"), STR("{:La}"), F(0x1.23456p+2)); + test(STR("1#23456p+3"), STR("{:La}"), F(0x1.23456p+3)); + test(STR("1#23456p+20"), STR("{:La}"), F(0x1.23456p+20)); + + test(STR("1.23456p-3"), en_US, STR("{:La}"), F(0x1.23456p-3)); + test(STR("1.23456p-2"), en_US, STR("{:La}"), F(0x1.23456p-2)); + test(STR("1.23456p-1"), en_US, STR("{:La}"), F(0x1.23456p-1)); + test(STR("1.23456p+0"), en_US, STR("{:La}"), F(0x1.23456p0)); + test(STR("1.23456p+1"), en_US, STR("{:La}"), F(0x1.23456p+1)); + test(STR("1.23456p+2"), en_US, STR("{:La}"), F(0x1.23456p+2)); + test(STR("1.23456p+3"), en_US, STR("{:La}"), F(0x1.23456p+3)); + test(STR("1.23456p+20"), en_US, STR("{:La}"), F(0x1.23456p+20)); + + std::locale::global(en_US); + test(STR("1#23456p-3"), loc, STR("{:La}"), F(0x1.23456p-3)); + test(STR("1#23456p-2"), loc, STR("{:La}"), F(0x1.23456p-2)); + test(STR("1#23456p-1"), loc, STR("{:La}"), F(0x1.23456p-1)); + test(STR("1#23456p+0"), loc, STR("{:La}"), F(0x1.23456p0)); + test(STR("1#23456p+1"), loc, STR("{:La}"), F(0x1.23456p+1)); + test(STR("1#23456p+2"), loc, STR("{:La}"), F(0x1.23456p+2)); + test(STR("1#23456p+3"), loc, STR("{:La}"), F(0x1.23456p+3)); + test(STR("1#23456p+20"), loc, STR("{:La}"), F(0x1.23456p+20)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1.23456p+3$$$"), STR("{:$<13La}"), F(0x1.23456p3)); + test(STR("$$$1.23456p+3"), STR("{:$>13La}"), F(0x1.23456p3)); + test(STR("$1.23456p+3$$"), STR("{:$^13La}"), F(0x1.23456p3)); + test(STR("0001.23456p+3"), STR("{:013La}"), F(0x1.23456p3)); + test(STR("-1.23456p+3$$$"), STR("{:$<14La}"), F(-0x1.23456p3)); + test(STR("$$$-1.23456p+3"), STR("{:$>14La}"), F(-0x1.23456p3)); + test(STR("$-1.23456p+3$$"), STR("{:$^14La}"), F(-0x1.23456p3)); + test(STR("-0001.23456p+3"), STR("{:014La}"), F(-0x1.23456p3)); + + std::locale::global(loc); + test(STR("1#23456p+3$$$"), STR("{:$<13La}"), F(0x1.23456p3)); + test(STR("$$$1#23456p+3"), STR("{:$>13La}"), F(0x1.23456p3)); + test(STR("$1#23456p+3$$"), STR("{:$^13La}"), F(0x1.23456p3)); + test(STR("0001#23456p+3"), STR("{:013La}"), F(0x1.23456p3)); + test(STR("-1#23456p+3$$$"), STR("{:$<14La}"), F(-0x1.23456p3)); + test(STR("$$$-1#23456p+3"), STR("{:$>14La}"), F(-0x1.23456p3)); + test(STR("$-1#23456p+3$$"), STR("{:$^14La}"), F(-0x1.23456p3)); + test(STR("-0001#23456p+3"), STR("{:014La}"), F(-0x1.23456p3)); + + test(STR("1.23456p+3$$$"), en_US, STR("{:$<13La}"), F(0x1.23456p3)); + test(STR("$$$1.23456p+3"), en_US, STR("{:$>13La}"), F(0x1.23456p3)); + test(STR("$1.23456p+3$$"), en_US, STR("{:$^13La}"), F(0x1.23456p3)); + test(STR("0001.23456p+3"), en_US, STR("{:013La}"), F(0x1.23456p3)); + test(STR("-1.23456p+3$$$"), en_US, STR("{:$<14La}"), F(-0x1.23456p3)); + test(STR("$$$-1.23456p+3"), en_US, STR("{:$>14La}"), F(-0x1.23456p3)); + test(STR("$-1.23456p+3$$"), en_US, STR("{:$^14La}"), F(-0x1.23456p3)); + test(STR("-0001.23456p+3"), en_US, STR("{:014La}"), F(-0x1.23456p3)); + + std::locale::global(en_US); + test(STR("1#23456p+3$$$"), loc, STR("{:$<13La}"), F(0x1.23456p3)); + test(STR("$$$1#23456p+3"), loc, STR("{:$>13La}"), F(0x1.23456p3)); + test(STR("$1#23456p+3$$"), loc, STR("{:$^13La}"), F(0x1.23456p3)); + test(STR("0001#23456p+3"), loc, STR("{:013La}"), F(0x1.23456p3)); + test(STR("-1#23456p+3$$$"), loc, STR("{:$<14La}"), F(-0x1.23456p3)); + test(STR("$$$-1#23456p+3"), loc, STR("{:$>14La}"), F(-0x1.23456p3)); + test(STR("$-1#23456p+3$$"), loc, STR("{:$^14La}"), F(-0x1.23456p3)); + test(STR("-0001#23456p+3"), loc, STR("{:014La}"), F(-0x1.23456p3)); +} + +template +void test_floating_point_hex_upper_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.23456P-3"), STR("{:LA}"), F(0x1.23456p-3)); + test(STR("1.23456P-2"), STR("{:LA}"), F(0x1.23456p-2)); + test(STR("1.23456P-1"), STR("{:LA}"), F(0x1.23456p-1)); + test(STR("1.23456P+0"), STR("{:LA}"), F(0x1.23456p0)); + test(STR("1.23456P+1"), STR("{:LA}"), F(0x1.23456p+1)); + test(STR("1.23456P+2"), STR("{:LA}"), F(0x1.23456p+2)); + test(STR("1.23456P+3"), STR("{:LA}"), F(0x1.23456p+3)); + test(STR("1.23456P+20"), STR("{:LA}"), F(0x1.23456p+20)); + + std::locale::global(loc); + test(STR("1#23456P-3"), STR("{:LA}"), F(0x1.23456p-3)); + test(STR("1#23456P-2"), STR("{:LA}"), F(0x1.23456p-2)); + test(STR("1#23456P-1"), STR("{:LA}"), F(0x1.23456p-1)); + test(STR("1#23456P+0"), STR("{:LA}"), F(0x1.23456p0)); + test(STR("1#23456P+1"), STR("{:LA}"), F(0x1.23456p+1)); + test(STR("1#23456P+2"), STR("{:LA}"), F(0x1.23456p+2)); + test(STR("1#23456P+3"), STR("{:LA}"), F(0x1.23456p+3)); + test(STR("1#23456P+20"), STR("{:LA}"), F(0x1.23456p+20)); + + test(STR("1.23456P-3"), en_US, STR("{:LA}"), F(0x1.23456p-3)); + test(STR("1.23456P-2"), en_US, STR("{:LA}"), F(0x1.23456p-2)); + test(STR("1.23456P-1"), en_US, STR("{:LA}"), F(0x1.23456p-1)); + test(STR("1.23456P+0"), en_US, STR("{:LA}"), F(0x1.23456p0)); + test(STR("1.23456P+1"), en_US, STR("{:LA}"), F(0x1.23456p+1)); + test(STR("1.23456P+2"), en_US, STR("{:LA}"), F(0x1.23456p+2)); + test(STR("1.23456P+3"), en_US, STR("{:LA}"), F(0x1.23456p+3)); + test(STR("1.23456P+20"), en_US, STR("{:LA}"), F(0x1.23456p+20)); + + std::locale::global(en_US); + test(STR("1#23456P-3"), loc, STR("{:LA}"), F(0x1.23456p-3)); + test(STR("1#23456P-2"), loc, STR("{:LA}"), F(0x1.23456p-2)); + test(STR("1#23456P-1"), loc, STR("{:LA}"), F(0x1.23456p-1)); + test(STR("1#23456P+0"), loc, STR("{:LA}"), F(0x1.23456p0)); + test(STR("1#23456P+1"), loc, STR("{:LA}"), F(0x1.23456p+1)); + test(STR("1#23456P+2"), loc, STR("{:LA}"), F(0x1.23456p+2)); + test(STR("1#23456P+3"), loc, STR("{:LA}"), F(0x1.23456p+3)); + test(STR("1#23456P+20"), loc, STR("{:LA}"), F(0x1.23456p+20)); + + // *** Fill, align, zero Padding *** + std::locale::global(en_US); + test(STR("1.23456P+3$$$"), STR("{:$<13LA}"), F(0x1.23456p3)); + test(STR("$$$1.23456P+3"), STR("{:$>13LA}"), F(0x1.23456p3)); + test(STR("$1.23456P+3$$"), STR("{:$^13LA}"), F(0x1.23456p3)); + test(STR("0001.23456P+3"), STR("{:013LA}"), F(0x1.23456p3)); + test(STR("-1.23456P+3$$$"), STR("{:$<14LA}"), F(-0x1.23456p3)); + test(STR("$$$-1.23456P+3"), STR("{:$>14LA}"), F(-0x1.23456p3)); + test(STR("$-1.23456P+3$$"), STR("{:$^14LA}"), F(-0x1.23456p3)); + test(STR("-0001.23456P+3"), STR("{:014LA}"), F(-0x1.23456p3)); + + std::locale::global(loc); + test(STR("1#23456P+3$$$"), STR("{:$<13LA}"), F(0x1.23456p3)); + test(STR("$$$1#23456P+3"), STR("{:$>13LA}"), F(0x1.23456p3)); + test(STR("$1#23456P+3$$"), STR("{:$^13LA}"), F(0x1.23456p3)); + test(STR("0001#23456P+3"), STR("{:013LA}"), F(0x1.23456p3)); + test(STR("-1#23456P+3$$$"), STR("{:$<14LA}"), F(-0x1.23456p3)); + test(STR("$$$-1#23456P+3"), STR("{:$>14LA}"), F(-0x1.23456p3)); + test(STR("$-1#23456P+3$$"), STR("{:$^14LA}"), F(-0x1.23456p3)); + test(STR("-0001#23456P+3"), STR("{:014LA}"), F(-0x1.23456p3)); + + test(STR("1.23456P+3$$$"), en_US, STR("{:$<13LA}"), F(0x1.23456p3)); + test(STR("$$$1.23456P+3"), en_US, STR("{:$>13LA}"), F(0x1.23456p3)); + test(STR("$1.23456P+3$$"), en_US, STR("{:$^13LA}"), F(0x1.23456p3)); + test(STR("0001.23456P+3"), en_US, STR("{:013LA}"), F(0x1.23456p3)); + test(STR("-1.23456P+3$$$"), en_US, STR("{:$<14LA}"), F(-0x1.23456p3)); + test(STR("$$$-1.23456P+3"), en_US, STR("{:$>14LA}"), F(-0x1.23456p3)); + test(STR("$-1.23456P+3$$"), en_US, STR("{:$^14LA}"), F(-0x1.23456p3)); + test(STR("-0001.23456P+3"), en_US, STR("{:014LA}"), F(-0x1.23456p3)); + + std::locale::global(en_US); + test(STR("1#23456P+3$$$"), loc, STR("{:$<13LA}"), F(0x1.23456p3)); + test(STR("$$$1#23456P+3"), loc, STR("{:$>13LA}"), F(0x1.23456p3)); + test(STR("$1#23456P+3$$"), loc, STR("{:$^13LA}"), F(0x1.23456p3)); + test(STR("0001#23456P+3"), loc, STR("{:013LA}"), F(0x1.23456p3)); + test(STR("-1#23456P+3$$$"), loc, STR("{:$<14LA}"), F(-0x1.23456p3)); + test(STR("$$$-1#23456P+3"), loc, STR("{:$>14LA}"), F(-0x1.23456p3)); + test(STR("$-1#23456P+3$$"), loc, STR("{:$^14LA}"), F(-0x1.23456p3)); + test(STR("-0001#23456P+3"), loc, STR("{:014LA}"), F(-0x1.23456p3)); +} + +template +void test_floating_point_hex_lower_case_precision() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.234560p-3"), STR("{:.6La}"), F(0x1.23456p-3)); + test(STR("1.234560p-2"), STR("{:.6La}"), F(0x1.23456p-2)); + test(STR("1.234560p-1"), STR("{:.6La}"), F(0x1.23456p-1)); + test(STR("1.234560p+0"), STR("{:.6La}"), F(0x1.23456p0)); + test(STR("1.234560p+1"), STR("{:.6La}"), F(0x1.23456p+1)); + test(STR("1.234560p+2"), STR("{:.6La}"), F(0x1.23456p+2)); + test(STR("1.234560p+3"), STR("{:.6La}"), F(0x1.23456p+3)); + test(STR("1.234560p+20"), STR("{:.6La}"), F(0x1.23456p+20)); + + std::locale::global(loc); + test(STR("1#234560p-3"), STR("{:.6La}"), F(0x1.23456p-3)); + test(STR("1#234560p-2"), STR("{:.6La}"), F(0x1.23456p-2)); + test(STR("1#234560p-1"), STR("{:.6La}"), F(0x1.23456p-1)); + test(STR("1#234560p+0"), STR("{:.6La}"), F(0x1.23456p0)); + test(STR("1#234560p+1"), STR("{:.6La}"), F(0x1.23456p+1)); + test(STR("1#234560p+2"), STR("{:.6La}"), F(0x1.23456p+2)); + test(STR("1#234560p+3"), STR("{:.6La}"), F(0x1.23456p+3)); + test(STR("1#234560p+20"), STR("{:.6La}"), F(0x1.23456p+20)); + + test(STR("1.234560p-3"), en_US, STR("{:.6La}"), F(0x1.23456p-3)); + test(STR("1.234560p-2"), en_US, STR("{:.6La}"), F(0x1.23456p-2)); + test(STR("1.234560p-1"), en_US, STR("{:.6La}"), F(0x1.23456p-1)); + test(STR("1.234560p+0"), en_US, STR("{:.6La}"), F(0x1.23456p0)); + test(STR("1.234560p+1"), en_US, STR("{:.6La}"), F(0x1.23456p+1)); + test(STR("1.234560p+2"), en_US, STR("{:.6La}"), F(0x1.23456p+2)); + test(STR("1.234560p+3"), en_US, STR("{:.6La}"), F(0x1.23456p+3)); + test(STR("1.234560p+20"), en_US, STR("{:.6La}"), F(0x1.23456p+20)); + + std::locale::global(en_US); + test(STR("1#234560p-3"), loc, STR("{:.6La}"), F(0x1.23456p-3)); + test(STR("1#234560p-2"), loc, STR("{:.6La}"), F(0x1.23456p-2)); + test(STR("1#234560p-1"), loc, STR("{:.6La}"), F(0x1.23456p-1)); + test(STR("1#234560p+0"), loc, STR("{:.6La}"), F(0x1.23456p0)); + test(STR("1#234560p+1"), loc, STR("{:.6La}"), F(0x1.23456p+1)); + test(STR("1#234560p+2"), loc, STR("{:.6La}"), F(0x1.23456p+2)); + test(STR("1#234560p+3"), loc, STR("{:.6La}"), F(0x1.23456p+3)); + test(STR("1#234560p+20"), loc, STR("{:.6La}"), F(0x1.23456p+20)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1.234560p+3$$$"), STR("{:$<14.6La}"), F(0x1.23456p3)); + test(STR("$$$1.234560p+3"), STR("{:$>14.6La}"), F(0x1.23456p3)); + test(STR("$1.234560p+3$$"), STR("{:$^14.6La}"), F(0x1.23456p3)); + test(STR("0001.234560p+3"), STR("{:014.6La}"), F(0x1.23456p3)); + test(STR("-1.234560p+3$$$"), STR("{:$<15.6La}"), F(-0x1.23456p3)); + test(STR("$$$-1.234560p+3"), STR("{:$>15.6La}"), F(-0x1.23456p3)); + test(STR("$-1.234560p+3$$"), STR("{:$^15.6La}"), F(-0x1.23456p3)); + test(STR("-0001.234560p+3"), STR("{:015.6La}"), F(-0x1.23456p3)); + + std::locale::global(loc); + test(STR("1#234560p+3$$$"), STR("{:$<14.6La}"), F(0x1.23456p3)); + test(STR("$$$1#234560p+3"), STR("{:$>14.6La}"), F(0x1.23456p3)); + test(STR("$1#234560p+3$$"), STR("{:$^14.6La}"), F(0x1.23456p3)); + test(STR("0001#234560p+3"), STR("{:014.6La}"), F(0x1.23456p3)); + test(STR("-1#234560p+3$$$"), STR("{:$<15.6La}"), F(-0x1.23456p3)); + test(STR("$$$-1#234560p+3"), STR("{:$>15.6La}"), F(-0x1.23456p3)); + test(STR("$-1#234560p+3$$"), STR("{:$^15.6La}"), F(-0x1.23456p3)); + test(STR("-0001#234560p+3"), STR("{:015.6La}"), F(-0x1.23456p3)); + + test(STR("1.234560p+3$$$"), en_US, STR("{:$<14.6La}"), F(0x1.23456p3)); + test(STR("$$$1.234560p+3"), en_US, STR("{:$>14.6La}"), F(0x1.23456p3)); + test(STR("$1.234560p+3$$"), en_US, STR("{:$^14.6La}"), F(0x1.23456p3)); + test(STR("0001.234560p+3"), en_US, STR("{:014.6La}"), F(0x1.23456p3)); + test(STR("-1.234560p+3$$$"), en_US, STR("{:$<15.6La}"), F(-0x1.23456p3)); + test(STR("$$$-1.234560p+3"), en_US, STR("{:$>15.6La}"), F(-0x1.23456p3)); + test(STR("$-1.234560p+3$$"), en_US, STR("{:$^15.6La}"), F(-0x1.23456p3)); + test(STR("-0001.234560p+3"), en_US, STR("{:015.6La}"), F(-0x1.23456p3)); + + std::locale::global(en_US); + test(STR("1#234560p+3$$$"), loc, STR("{:$<14.6La}"), F(0x1.23456p3)); + test(STR("$$$1#234560p+3"), loc, STR("{:$>14.6La}"), F(0x1.23456p3)); + test(STR("$1#234560p+3$$"), loc, STR("{:$^14.6La}"), F(0x1.23456p3)); + test(STR("0001#234560p+3"), loc, STR("{:014.6La}"), F(0x1.23456p3)); + test(STR("-1#234560p+3$$$"), loc, STR("{:$<15.6La}"), F(-0x1.23456p3)); + test(STR("$$$-1#234560p+3"), loc, STR("{:$>15.6La}"), F(-0x1.23456p3)); + test(STR("$-1#234560p+3$$"), loc, STR("{:$^15.6La}"), F(-0x1.23456p3)); + test(STR("-0001#234560p+3"), loc, STR("{:015.6La}"), F(-0x1.23456p3)); +} + +template +void test_floating_point_hex_upper_case_precision() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.234560P-3"), STR("{:.6LA}"), F(0x1.23456p-3)); + test(STR("1.234560P-2"), STR("{:.6LA}"), F(0x1.23456p-2)); + test(STR("1.234560P-1"), STR("{:.6LA}"), F(0x1.23456p-1)); + test(STR("1.234560P+0"), STR("{:.6LA}"), F(0x1.23456p0)); + test(STR("1.234560P+1"), STR("{:.6LA}"), F(0x1.23456p+1)); + test(STR("1.234560P+2"), STR("{:.6LA}"), F(0x1.23456p+2)); + test(STR("1.234560P+3"), STR("{:.6LA}"), F(0x1.23456p+3)); + test(STR("1.234560P+20"), STR("{:.6LA}"), F(0x1.23456p+20)); + + std::locale::global(loc); + test(STR("1#234560P-3"), STR("{:.6LA}"), F(0x1.23456p-3)); + test(STR("1#234560P-2"), STR("{:.6LA}"), F(0x1.23456p-2)); + test(STR("1#234560P-1"), STR("{:.6LA}"), F(0x1.23456p-1)); + test(STR("1#234560P+0"), STR("{:.6LA}"), F(0x1.23456p0)); + test(STR("1#234560P+1"), STR("{:.6LA}"), F(0x1.23456p+1)); + test(STR("1#234560P+2"), STR("{:.6LA}"), F(0x1.23456p+2)); + test(STR("1#234560P+3"), STR("{:.6LA}"), F(0x1.23456p+3)); + test(STR("1#234560P+20"), STR("{:.6LA}"), F(0x1.23456p+20)); + + test(STR("1.234560P-3"), en_US, STR("{:.6LA}"), F(0x1.23456p-3)); + test(STR("1.234560P-2"), en_US, STR("{:.6LA}"), F(0x1.23456p-2)); + test(STR("1.234560P-1"), en_US, STR("{:.6LA}"), F(0x1.23456p-1)); + test(STR("1.234560P+0"), en_US, STR("{:.6LA}"), F(0x1.23456p0)); + test(STR("1.234560P+1"), en_US, STR("{:.6LA}"), F(0x1.23456p+1)); + test(STR("1.234560P+2"), en_US, STR("{:.6LA}"), F(0x1.23456p+2)); + test(STR("1.234560P+3"), en_US, STR("{:.6LA}"), F(0x1.23456p+3)); + test(STR("1.234560P+20"), en_US, STR("{:.6LA}"), F(0x1.23456p+20)); + + std::locale::global(en_US); + test(STR("1#234560P-3"), loc, STR("{:.6LA}"), F(0x1.23456p-3)); + test(STR("1#234560P-2"), loc, STR("{:.6LA}"), F(0x1.23456p-2)); + test(STR("1#234560P-1"), loc, STR("{:.6LA}"), F(0x1.23456p-1)); + test(STR("1#234560P+0"), loc, STR("{:.6LA}"), F(0x1.23456p0)); + test(STR("1#234560P+1"), loc, STR("{:.6LA}"), F(0x1.23456p+1)); + test(STR("1#234560P+2"), loc, STR("{:.6LA}"), F(0x1.23456p+2)); + test(STR("1#234560P+3"), loc, STR("{:.6LA}"), F(0x1.23456p+3)); + test(STR("1#234560P+20"), loc, STR("{:.6LA}"), F(0x1.23456p+20)); + + // *** Fill, align, zero Padding *** + std::locale::global(en_US); + test(STR("1.234560P+3$$$"), STR("{:$<14.6LA}"), F(0x1.23456p3)); + test(STR("$$$1.234560P+3"), STR("{:$>14.6LA}"), F(0x1.23456p3)); + test(STR("$1.234560P+3$$"), STR("{:$^14.6LA}"), F(0x1.23456p3)); + test(STR("0001.234560P+3"), STR("{:014.6LA}"), F(0x1.23456p3)); + test(STR("-1.234560P+3$$$"), STR("{:$<15.6LA}"), F(-0x1.23456p3)); + test(STR("$$$-1.234560P+3"), STR("{:$>15.6LA}"), F(-0x1.23456p3)); + test(STR("$-1.234560P+3$$"), STR("{:$^15.6LA}"), F(-0x1.23456p3)); + test(STR("-0001.234560P+3"), STR("{:015.6LA}"), F(-0x1.23456p3)); + + std::locale::global(loc); + test(STR("1#234560P+3$$$"), STR("{:$<14.6LA}"), F(0x1.23456p3)); + test(STR("$$$1#234560P+3"), STR("{:$>14.6LA}"), F(0x1.23456p3)); + test(STR("$1#234560P+3$$"), STR("{:$^14.6LA}"), F(0x1.23456p3)); + test(STR("0001#234560P+3"), STR("{:014.6LA}"), F(0x1.23456p3)); + test(STR("-1#234560P+3$$$"), STR("{:$<15.6LA}"), F(-0x1.23456p3)); + test(STR("$$$-1#234560P+3"), STR("{:$>15.6LA}"), F(-0x1.23456p3)); + test(STR("$-1#234560P+3$$"), STR("{:$^15.6LA}"), F(-0x1.23456p3)); + test(STR("-0001#234560P+3"), STR("{:015.6LA}"), F(-0x1.23456p3)); + + test(STR("1.234560P+3$$$"), en_US, STR("{:$<14.6LA}"), F(0x1.23456p3)); + test(STR("$$$1.234560P+3"), en_US, STR("{:$>14.6LA}"), F(0x1.23456p3)); + test(STR("$1.234560P+3$$"), en_US, STR("{:$^14.6LA}"), F(0x1.23456p3)); + test(STR("0001.234560P+3"), en_US, STR("{:014.6LA}"), F(0x1.23456p3)); + test(STR("-1.234560P+3$$$"), en_US, STR("{:$<15.6LA}"), F(-0x1.23456p3)); + test(STR("$$$-1.234560P+3"), en_US, STR("{:$>15.6LA}"), F(-0x1.23456p3)); + test(STR("$-1.234560P+3$$"), en_US, STR("{:$^15.6LA}"), F(-0x1.23456p3)); + test(STR("-0001.234560P+3"), en_US, STR("{:015.6LA}"), F(-0x1.23456p3)); + + std::locale::global(en_US); + test(STR("1#234560P+3$$$"), loc, STR("{:$<14.6LA}"), F(0x1.23456p3)); + test(STR("$$$1#234560P+3"), loc, STR("{:$>14.6LA}"), F(0x1.23456p3)); + test(STR("$1#234560P+3$$"), loc, STR("{:$^14.6LA}"), F(0x1.23456p3)); + test(STR("0001#234560P+3"), loc, STR("{:014.6LA}"), F(0x1.23456p3)); + test(STR("-1#234560P+3$$$"), loc, STR("{:$<15.6LA}"), F(-0x1.23456p3)); + test(STR("$$$-1#234560P+3"), loc, STR("{:$>15.6LA}"), F(-0x1.23456p3)); + test(STR("$-1#234560P+3$$"), loc, STR("{:$^15.6LA}"), F(-0x1.23456p3)); + test(STR("-0001#234560P+3"), loc, STR("{:015.6LA}"), F(-0x1.23456p3)); +} + +template +void test_floating_point_scientific_lower_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.234567e-03"), STR("{:.6Le}"), F(1.234567e-3)); + test(STR("1.234567e-02"), STR("{:.6Le}"), F(1.234567e-2)); + test(STR("1.234567e-01"), STR("{:.6Le}"), F(1.234567e-1)); + test(STR("1.234567e+00"), STR("{:.6Le}"), F(1.234567e0)); + test(STR("1.234567e+01"), STR("{:.6Le}"), F(1.234567e1)); + test(STR("1.234567e+02"), STR("{:.6Le}"), F(1.234567e2)); + test(STR("1.234567e+03"), STR("{:.6Le}"), F(1.234567e3)); + test(STR("1.234567e+20"), STR("{:.6Le}"), F(1.234567e20)); + test(STR("-1.234567e-03"), STR("{:.6Le}"), F(-1.234567e-3)); + test(STR("-1.234567e-02"), STR("{:.6Le}"), F(-1.234567e-2)); + test(STR("-1.234567e-01"), STR("{:.6Le}"), F(-1.234567e-1)); + test(STR("-1.234567e+00"), STR("{:.6Le}"), F(-1.234567e0)); + test(STR("-1.234567e+01"), STR("{:.6Le}"), F(-1.234567e1)); + test(STR("-1.234567e+02"), STR("{:.6Le}"), F(-1.234567e2)); + test(STR("-1.234567e+03"), STR("{:.6Le}"), F(-1.234567e3)); + test(STR("-1.234567e+20"), STR("{:.6Le}"), F(-1.234567e20)); + + std::locale::global(loc); + test(STR("1#234567e-03"), STR("{:.6Le}"), F(1.234567e-3)); + test(STR("1#234567e-02"), STR("{:.6Le}"), F(1.234567e-2)); + test(STR("1#234567e-01"), STR("{:.6Le}"), F(1.234567e-1)); + test(STR("1#234567e+00"), STR("{:.6Le}"), F(1.234567e0)); + test(STR("1#234567e+01"), STR("{:.6Le}"), F(1.234567e1)); + test(STR("1#234567e+02"), STR("{:.6Le}"), F(1.234567e2)); + test(STR("1#234567e+03"), STR("{:.6Le}"), F(1.234567e3)); + test(STR("1#234567e+20"), STR("{:.6Le}"), F(1.234567e20)); + test(STR("-1#234567e-03"), STR("{:.6Le}"), F(-1.234567e-3)); + test(STR("-1#234567e-02"), STR("{:.6Le}"), F(-1.234567e-2)); + test(STR("-1#234567e-01"), STR("{:.6Le}"), F(-1.234567e-1)); + test(STR("-1#234567e+00"), STR("{:.6Le}"), F(-1.234567e0)); + test(STR("-1#234567e+01"), STR("{:.6Le}"), F(-1.234567e1)); + test(STR("-1#234567e+02"), STR("{:.6Le}"), F(-1.234567e2)); + test(STR("-1#234567e+03"), STR("{:.6Le}"), F(-1.234567e3)); + test(STR("-1#234567e+20"), STR("{:.6Le}"), F(-1.234567e20)); + + test(STR("1.234567e-03"), en_US, STR("{:.6Le}"), F(1.234567e-3)); + test(STR("1.234567e-02"), en_US, STR("{:.6Le}"), F(1.234567e-2)); + test(STR("1.234567e-01"), en_US, STR("{:.6Le}"), F(1.234567e-1)); + test(STR("1.234567e+00"), en_US, STR("{:.6Le}"), F(1.234567e0)); + test(STR("1.234567e+01"), en_US, STR("{:.6Le}"), F(1.234567e1)); + test(STR("1.234567e+02"), en_US, STR("{:.6Le}"), F(1.234567e2)); + test(STR("1.234567e+03"), en_US, STR("{:.6Le}"), F(1.234567e3)); + test(STR("1.234567e+20"), en_US, STR("{:.6Le}"), F(1.234567e20)); + test(STR("-1.234567e-03"), en_US, STR("{:.6Le}"), F(-1.234567e-3)); + test(STR("-1.234567e-02"), en_US, STR("{:.6Le}"), F(-1.234567e-2)); + test(STR("-1.234567e-01"), en_US, STR("{:.6Le}"), F(-1.234567e-1)); + test(STR("-1.234567e+00"), en_US, STR("{:.6Le}"), F(-1.234567e0)); + test(STR("-1.234567e+01"), en_US, STR("{:.6Le}"), F(-1.234567e1)); + test(STR("-1.234567e+02"), en_US, STR("{:.6Le}"), F(-1.234567e2)); + test(STR("-1.234567e+03"), en_US, STR("{:.6Le}"), F(-1.234567e3)); + test(STR("-1.234567e+20"), en_US, STR("{:.6Le}"), F(-1.234567e20)); + + std::locale::global(en_US); + test(STR("1#234567e-03"), loc, STR("{:.6Le}"), F(1.234567e-3)); + test(STR("1#234567e-02"), loc, STR("{:.6Le}"), F(1.234567e-2)); + test(STR("1#234567e-01"), loc, STR("{:.6Le}"), F(1.234567e-1)); + test(STR("1#234567e+00"), loc, STR("{:.6Le}"), F(1.234567e0)); + test(STR("1#234567e+01"), loc, STR("{:.6Le}"), F(1.234567e1)); + test(STR("1#234567e+02"), loc, STR("{:.6Le}"), F(1.234567e2)); + test(STR("1#234567e+03"), loc, STR("{:.6Le}"), F(1.234567e3)); + test(STR("1#234567e+20"), loc, STR("{:.6Le}"), F(1.234567e20)); + test(STR("-1#234567e-03"), loc, STR("{:.6Le}"), F(-1.234567e-3)); + test(STR("-1#234567e-02"), loc, STR("{:.6Le}"), F(-1.234567e-2)); + test(STR("-1#234567e-01"), loc, STR("{:.6Le}"), F(-1.234567e-1)); + test(STR("-1#234567e+00"), loc, STR("{:.6Le}"), F(-1.234567e0)); + test(STR("-1#234567e+01"), loc, STR("{:.6Le}"), F(-1.234567e1)); + test(STR("-1#234567e+02"), loc, STR("{:.6Le}"), F(-1.234567e2)); + test(STR("-1#234567e+03"), loc, STR("{:.6Le}"), F(-1.234567e3)); + test(STR("-1#234567e+20"), loc, STR("{:.6Le}"), F(-1.234567e20)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1.234567e+03$$$"), STR("{:$<15.6Le}"), F(1.234567e3)); + test(STR("$$$1.234567e+03"), STR("{:$>15.6Le}"), F(1.234567e3)); + test(STR("$1.234567e+03$$"), STR("{:$^15.6Le}"), F(1.234567e3)); + test(STR("0001.234567e+03"), STR("{:015.6Le}"), F(1.234567e3)); + test(STR("-1.234567e+03$$$"), STR("{:$<16.6Le}"), F(-1.234567e3)); + test(STR("$$$-1.234567e+03"), STR("{:$>16.6Le}"), F(-1.234567e3)); + test(STR("$-1.234567e+03$$"), STR("{:$^16.6Le}"), F(-1.234567e3)); + test(STR("-0001.234567e+03"), STR("{:016.6Le}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1#234567e+03$$$"), STR("{:$<15.6Le}"), F(1.234567e3)); + test(STR("$$$1#234567e+03"), STR("{:$>15.6Le}"), F(1.234567e3)); + test(STR("$1#234567e+03$$"), STR("{:$^15.6Le}"), F(1.234567e3)); + test(STR("0001#234567e+03"), STR("{:015.6Le}"), F(1.234567e3)); + test(STR("-1#234567e+03$$$"), STR("{:$<16.6Le}"), F(-1.234567e3)); + test(STR("$$$-1#234567e+03"), STR("{:$>16.6Le}"), F(-1.234567e3)); + test(STR("$-1#234567e+03$$"), STR("{:$^16.6Le}"), F(-1.234567e3)); + test(STR("-0001#234567e+03"), STR("{:016.6Le}"), F(-1.234567e3)); + + test(STR("1.234567e+03$$$"), en_US, STR("{:$<15.6Le}"), F(1.234567e3)); + test(STR("$$$1.234567e+03"), en_US, STR("{:$>15.6Le}"), F(1.234567e3)); + test(STR("$1.234567e+03$$"), en_US, STR("{:$^15.6Le}"), F(1.234567e3)); + test(STR("0001.234567e+03"), en_US, STR("{:015.6Le}"), F(1.234567e3)); + test(STR("-1.234567e+03$$$"), en_US, STR("{:$<16.6Le}"), F(-1.234567e3)); + test(STR("$$$-1.234567e+03"), en_US, STR("{:$>16.6Le}"), F(-1.234567e3)); + test(STR("$-1.234567e+03$$"), en_US, STR("{:$^16.6Le}"), F(-1.234567e3)); + test(STR("-0001.234567e+03"), en_US, STR("{:016.6Le}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1#234567e+03$$$"), loc, STR("{:$<15.6Le}"), F(1.234567e3)); + test(STR("$$$1#234567e+03"), loc, STR("{:$>15.6Le}"), F(1.234567e3)); + test(STR("$1#234567e+03$$"), loc, STR("{:$^15.6Le}"), F(1.234567e3)); + test(STR("0001#234567e+03"), loc, STR("{:015.6Le}"), F(1.234567e3)); + test(STR("-1#234567e+03$$$"), loc, STR("{:$<16.6Le}"), F(-1.234567e3)); + test(STR("$$$-1#234567e+03"), loc, STR("{:$>16.6Le}"), F(-1.234567e3)); + test(STR("$-1#234567e+03$$"), loc, STR("{:$^16.6Le}"), F(-1.234567e3)); + test(STR("-0001#234567e+03"), loc, STR("{:016.6Le}"), F(-1.234567e3)); +} + +template +void test_floating_point_scientific_upper_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.234567E-03"), STR("{:.6LE}"), F(1.234567e-3)); + test(STR("1.234567E-02"), STR("{:.6LE}"), F(1.234567e-2)); + test(STR("1.234567E-01"), STR("{:.6LE}"), F(1.234567e-1)); + test(STR("1.234567E+00"), STR("{:.6LE}"), F(1.234567e0)); + test(STR("1.234567E+01"), STR("{:.6LE}"), F(1.234567e1)); + test(STR("1.234567E+02"), STR("{:.6LE}"), F(1.234567e2)); + test(STR("1.234567E+03"), STR("{:.6LE}"), F(1.234567e3)); + test(STR("1.234567E+20"), STR("{:.6LE}"), F(1.234567e20)); + test(STR("-1.234567E-03"), STR("{:.6LE}"), F(-1.234567e-3)); + test(STR("-1.234567E-02"), STR("{:.6LE}"), F(-1.234567e-2)); + test(STR("-1.234567E-01"), STR("{:.6LE}"), F(-1.234567e-1)); + test(STR("-1.234567E+00"), STR("{:.6LE}"), F(-1.234567e0)); + test(STR("-1.234567E+01"), STR("{:.6LE}"), F(-1.234567e1)); + test(STR("-1.234567E+02"), STR("{:.6LE}"), F(-1.234567e2)); + test(STR("-1.234567E+03"), STR("{:.6LE}"), F(-1.234567e3)); + test(STR("-1.234567E+20"), STR("{:.6LE}"), F(-1.234567e20)); + + std::locale::global(loc); + test(STR("1#234567E-03"), STR("{:.6LE}"), F(1.234567e-3)); + test(STR("1#234567E-02"), STR("{:.6LE}"), F(1.234567e-2)); + test(STR("1#234567E-01"), STR("{:.6LE}"), F(1.234567e-1)); + test(STR("1#234567E+00"), STR("{:.6LE}"), F(1.234567e0)); + test(STR("1#234567E+01"), STR("{:.6LE}"), F(1.234567e1)); + test(STR("1#234567E+02"), STR("{:.6LE}"), F(1.234567e2)); + test(STR("1#234567E+03"), STR("{:.6LE}"), F(1.234567e3)); + test(STR("1#234567E+20"), STR("{:.6LE}"), F(1.234567e20)); + test(STR("-1#234567E-03"), STR("{:.6LE}"), F(-1.234567e-3)); + test(STR("-1#234567E-02"), STR("{:.6LE}"), F(-1.234567e-2)); + test(STR("-1#234567E-01"), STR("{:.6LE}"), F(-1.234567e-1)); + test(STR("-1#234567E+00"), STR("{:.6LE}"), F(-1.234567e0)); + test(STR("-1#234567E+01"), STR("{:.6LE}"), F(-1.234567e1)); + test(STR("-1#234567E+02"), STR("{:.6LE}"), F(-1.234567e2)); + test(STR("-1#234567E+03"), STR("{:.6LE}"), F(-1.234567e3)); + test(STR("-1#234567E+20"), STR("{:.6LE}"), F(-1.234567e20)); + + test(STR("1.234567E-03"), en_US, STR("{:.6LE}"), F(1.234567e-3)); + test(STR("1.234567E-02"), en_US, STR("{:.6LE}"), F(1.234567e-2)); + test(STR("1.234567E-01"), en_US, STR("{:.6LE}"), F(1.234567e-1)); + test(STR("1.234567E+00"), en_US, STR("{:.6LE}"), F(1.234567e0)); + test(STR("1.234567E+01"), en_US, STR("{:.6LE}"), F(1.234567e1)); + test(STR("1.234567E+02"), en_US, STR("{:.6LE}"), F(1.234567e2)); + test(STR("1.234567E+03"), en_US, STR("{:.6LE}"), F(1.234567e3)); + test(STR("1.234567E+20"), en_US, STR("{:.6LE}"), F(1.234567e20)); + test(STR("-1.234567E-03"), en_US, STR("{:.6LE}"), F(-1.234567e-3)); + test(STR("-1.234567E-02"), en_US, STR("{:.6LE}"), F(-1.234567e-2)); + test(STR("-1.234567E-01"), en_US, STR("{:.6LE}"), F(-1.234567e-1)); + test(STR("-1.234567E+00"), en_US, STR("{:.6LE}"), F(-1.234567e0)); + test(STR("-1.234567E+01"), en_US, STR("{:.6LE}"), F(-1.234567e1)); + test(STR("-1.234567E+02"), en_US, STR("{:.6LE}"), F(-1.234567e2)); + test(STR("-1.234567E+03"), en_US, STR("{:.6LE}"), F(-1.234567e3)); + test(STR("-1.234567E+20"), en_US, STR("{:.6LE}"), F(-1.234567e20)); + + std::locale::global(en_US); + test(STR("1#234567E-03"), loc, STR("{:.6LE}"), F(1.234567e-3)); + test(STR("1#234567E-02"), loc, STR("{:.6LE}"), F(1.234567e-2)); + test(STR("1#234567E-01"), loc, STR("{:.6LE}"), F(1.234567e-1)); + test(STR("1#234567E+00"), loc, STR("{:.6LE}"), F(1.234567e0)); + test(STR("1#234567E+01"), loc, STR("{:.6LE}"), F(1.234567e1)); + test(STR("1#234567E+02"), loc, STR("{:.6LE}"), F(1.234567e2)); + test(STR("1#234567E+03"), loc, STR("{:.6LE}"), F(1.234567e3)); + test(STR("1#234567E+20"), loc, STR("{:.6LE}"), F(1.234567e20)); + test(STR("-1#234567E-03"), loc, STR("{:.6LE}"), F(-1.234567e-3)); + test(STR("-1#234567E-02"), loc, STR("{:.6LE}"), F(-1.234567e-2)); + test(STR("-1#234567E-01"), loc, STR("{:.6LE}"), F(-1.234567e-1)); + test(STR("-1#234567E+00"), loc, STR("{:.6LE}"), F(-1.234567e0)); + test(STR("-1#234567E+01"), loc, STR("{:.6LE}"), F(-1.234567e1)); + test(STR("-1#234567E+02"), loc, STR("{:.6LE}"), F(-1.234567e2)); + test(STR("-1#234567E+03"), loc, STR("{:.6LE}"), F(-1.234567e3)); + test(STR("-1#234567E+20"), loc, STR("{:.6LE}"), F(-1.234567e20)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1.234567E+03$$$"), STR("{:$<15.6LE}"), F(1.234567e3)); + test(STR("$$$1.234567E+03"), STR("{:$>15.6LE}"), F(1.234567e3)); + test(STR("$1.234567E+03$$"), STR("{:$^15.6LE}"), F(1.234567e3)); + test(STR("0001.234567E+03"), STR("{:015.6LE}"), F(1.234567e3)); + test(STR("-1.234567E+03$$$"), STR("{:$<16.6LE}"), F(-1.234567e3)); + test(STR("$$$-1.234567E+03"), STR("{:$>16.6LE}"), F(-1.234567e3)); + test(STR("$-1.234567E+03$$"), STR("{:$^16.6LE}"), F(-1.234567e3)); + test(STR("-0001.234567E+03"), STR("{:016.6LE}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1#234567E+03$$$"), STR("{:$<15.6LE}"), F(1.234567e3)); + test(STR("$$$1#234567E+03"), STR("{:$>15.6LE}"), F(1.234567e3)); + test(STR("$1#234567E+03$$"), STR("{:$^15.6LE}"), F(1.234567e3)); + test(STR("0001#234567E+03"), STR("{:015.6LE}"), F(1.234567e3)); + test(STR("-1#234567E+03$$$"), STR("{:$<16.6LE}"), F(-1.234567e3)); + test(STR("$$$-1#234567E+03"), STR("{:$>16.6LE}"), F(-1.234567e3)); + test(STR("$-1#234567E+03$$"), STR("{:$^16.6LE}"), F(-1.234567e3)); + test(STR("-0001#234567E+03"), STR("{:016.6LE}"), F(-1.234567e3)); + + test(STR("1.234567E+03$$$"), en_US, STR("{:$<15.6LE}"), F(1.234567e3)); + test(STR("$$$1.234567E+03"), en_US, STR("{:$>15.6LE}"), F(1.234567e3)); + test(STR("$1.234567E+03$$"), en_US, STR("{:$^15.6LE}"), F(1.234567e3)); + test(STR("0001.234567E+03"), en_US, STR("{:015.6LE}"), F(1.234567e3)); + test(STR("-1.234567E+03$$$"), en_US, STR("{:$<16.6LE}"), F(-1.234567e3)); + test(STR("$$$-1.234567E+03"), en_US, STR("{:$>16.6LE}"), F(-1.234567e3)); + test(STR("$-1.234567E+03$$"), en_US, STR("{:$^16.6LE}"), F(-1.234567e3)); + test(STR("-0001.234567E+03"), en_US, STR("{:016.6LE}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1#234567E+03$$$"), loc, STR("{:$<15.6LE}"), F(1.234567e3)); + test(STR("$$$1#234567E+03"), loc, STR("{:$>15.6LE}"), F(1.234567e3)); + test(STR("$1#234567E+03$$"), loc, STR("{:$^15.6LE}"), F(1.234567e3)); + test(STR("0001#234567E+03"), loc, STR("{:015.6LE}"), F(1.234567e3)); + test(STR("-1#234567E+03$$$"), loc, STR("{:$<16.6LE}"), F(-1.234567e3)); + test(STR("$$$-1#234567E+03"), loc, STR("{:$>16.6LE}"), F(-1.234567e3)); + test(STR("$-1#234567E+03$$"), loc, STR("{:$^16.6LE}"), F(-1.234567e3)); + test(STR("-0001#234567E+03"), loc, STR("{:016.6LE}"), F(-1.234567e3)); +} + +template +void test_floating_point_fixed_lower_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("0.000001"), STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0.000012"), STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0.000123"), STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0.001235"), STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0.012346"), STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0.123457"), STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1.234567"), STR("{:.6Lf}"), F(1.234567e0)); + test(STR("12.345670"), STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("123.456700"), STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1,234.567000"), STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12,345.670000"), STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123,456.700000"), STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1,234,567.000000"), STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12,345,670.000000"), STR("{:.6Lf}"), F(1.234567e7)); + test(STR("123,456,700,000,000,000,000.000000"), STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0.000001"), STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0.000012"), STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0.000123"), STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0.001235"), STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0.012346"), STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0.123457"), STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1.234567"), STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-12.345670"), STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-123.456700"), STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1,234.567000"), STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12,345.670000"), STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123,456.700000"), STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1,234,567.000000"), STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12,345,670.000000"), STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-123,456,700,000,000,000,000.000000"), STR("{:.6Lf}"), F(-1.234567e20)); + } + + std::locale::global(loc); + test(STR("0#000001"), STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0#000012"), STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0#000123"), STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0#001235"), STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0#012346"), STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0#123457"), STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1#234567"), STR("{:.6Lf}"), F(1.234567e0)); + test(STR("1_2#345670"), STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("12_3#456700"), STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1_23_4#567000"), STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12_34_5#670000"), STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123_45_6#700000"), STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1_234_56_7#000000"), STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12_345_67_0#000000"), STR("{:.6Lf}"), F(1.234567e7)); + test(STR("1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0#000001"), STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0#000012"), STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0#000123"), STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0#001235"), STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0#012346"), STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0#123457"), STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1#234567"), STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-1_2#345670"), STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-12_3#456700"), STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1_23_4#567000"), STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12_34_5#670000"), STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123_45_6#700000"), STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1_234_56_7#000000"), STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12_345_67_0#000000"), STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), STR("{:.6Lf}"), F(-1.234567e20)); + } + + test(STR("0.000001"), en_US, STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0.000012"), en_US, STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0.000123"), en_US, STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0.001235"), en_US, STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0.012346"), en_US, STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0.123457"), en_US, STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1.234567"), en_US, STR("{:.6Lf}"), F(1.234567e0)); + test(STR("12.345670"), en_US, STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("123.456700"), en_US, STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1,234.567000"), en_US, STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12,345.670000"), en_US, STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123,456.700000"), en_US, STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1,234,567.000000"), en_US, STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12,345,670.000000"), en_US, STR("{:.6Lf}"), F(1.234567e7)); + test(STR("123,456,700,000,000,000,000.000000"), en_US, STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0.000001"), en_US, STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0.000012"), en_US, STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0.000123"), en_US, STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0.001235"), en_US, STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0.012346"), en_US, STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0.123457"), en_US, STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1.234567"), en_US, STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-12.345670"), en_US, STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-123.456700"), en_US, STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1,234.567000"), en_US, STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12,345.670000"), en_US, STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123,456.700000"), en_US, STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1,234,567.000000"), en_US, STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12,345,670.000000"), en_US, STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-123,456,700,000,000,000,000.000000"), en_US, STR("{:.6Lf}"), F(-1.234567e20)); + } + + std::locale::global(en_US); + test(STR("0#000001"), loc, STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0#000012"), loc, STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0#000123"), loc, STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0#001235"), loc, STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0#012346"), loc, STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0#123457"), loc, STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1#234567"), loc, STR("{:.6Lf}"), F(1.234567e0)); + test(STR("1_2#345670"), loc, STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("12_3#456700"), loc, STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1_23_4#567000"), loc, STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12_34_5#670000"), loc, STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123_45_6#700000"), loc, STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1_234_56_7#000000"), loc, STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12_345_67_0#000000"), loc, STR("{:.6Lf}"), F(1.234567e7)); + test(STR("1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), loc, STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0#000001"), loc, STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0#000012"), loc, STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0#000123"), loc, STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0#001235"), loc, STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0#012346"), loc, STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0#123457"), loc, STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1#234567"), loc, STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-1_2#345670"), loc, STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-12_3#456700"), loc, STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1_23_4#567000"), loc, STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12_34_5#670000"), loc, STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123_45_6#700000"), loc, STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1_234_56_7#000000"), loc, STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12_345_67_0#000000"), loc, STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), loc, STR("{:.6Lf}"), F(-1.234567e20)); + } + + // *** Fill, align, zero padding *** + if constexpr (sizeof(F) > sizeof(float)) { + std::locale::global(en_US); + test(STR("1,234.567000$$$"), STR("{:$<15.6Lf}"), F(1.234567e3)); + test(STR("$$$1,234.567000"), STR("{:$>15.6Lf}"), F(1.234567e3)); + test(STR("$1,234.567000$$"), STR("{:$^15.6Lf}"), F(1.234567e3)); + test(STR("0001,234.567000"), STR("{:015.6Lf}"), F(1.234567e3)); + test(STR("-1,234.567000$$$"), STR("{:$<16.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1,234.567000"), STR("{:$>16.6Lf}"), F(-1.234567e3)); + test(STR("$-1,234.567000$$"), STR("{:$^16.6Lf}"), F(-1.234567e3)); + test(STR("-0001,234.567000"), STR("{:016.6Lf}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1_23_4#567000$$$"), STR("{:$<16.6Lf}"), F(1.234567e3)); + test(STR("$$$1_23_4#567000"), STR("{:$>16.6Lf}"), F(1.234567e3)); + test(STR("$1_23_4#567000$$"), STR("{:$^16.6Lf}"), F(1.234567e3)); + test(STR("0001_23_4#567000"), STR("{:016.6Lf}"), F(1.234567e3)); + test(STR("-1_23_4#567000$$$"), STR("{:$<17.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#567000"), STR("{:$>17.6Lf}"), F(-1.234567e3)); + test(STR("$-1_23_4#567000$$"), STR("{:$^17.6Lf}"), F(-1.234567e3)); + test(STR("-0001_23_4#567000"), STR("{:017.6Lf}"), F(-1.234567e3)); + + test(STR("1,234.567000$$$"), en_US, STR("{:$<15.6Lf}"), F(1.234567e3)); + test(STR("$$$1,234.567000"), en_US, STR("{:$>15.6Lf}"), F(1.234567e3)); + test(STR("$1,234.567000$$"), en_US, STR("{:$^15.6Lf}"), F(1.234567e3)); + test(STR("0001,234.567000"), en_US, STR("{:015.6Lf}"), F(1.234567e3)); + test(STR("-1,234.567000$$$"), en_US, STR("{:$<16.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1,234.567000"), en_US, STR("{:$>16.6Lf}"), F(-1.234567e3)); + test(STR("$-1,234.567000$$"), en_US, STR("{:$^16.6Lf}"), F(-1.234567e3)); + test(STR("-0001,234.567000"), en_US, STR("{:016.6Lf}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1_23_4#567000$$$"), loc, STR("{:$<16.6Lf}"), F(1.234567e3)); + test(STR("$$$1_23_4#567000"), loc, STR("{:$>16.6Lf}"), F(1.234567e3)); + test(STR("$1_23_4#567000$$"), loc, STR("{:$^16.6Lf}"), F(1.234567e3)); + test(STR("0001_23_4#567000"), loc, STR("{:016.6Lf}"), F(1.234567e3)); + test(STR("-1_23_4#567000$$$"), loc, STR("{:$<17.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#567000"), loc, STR("{:$>17.6Lf}"), F(-1.234567e3)); + test(STR("$-1_23_4#567000$$"), loc, STR("{:$^17.6Lf}"), F(-1.234567e3)); + test(STR("-0001_23_4#567000"), loc, STR("{:017.6Lf}"), F(-1.234567e3)); + } +} + +template +void test_floating_point_fixed_upper_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("0.000001"), STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0.000012"), STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0.000123"), STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0.001235"), STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0.012346"), STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0.123457"), STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1.234567"), STR("{:.6Lf}"), F(1.234567e0)); + test(STR("12.345670"), STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("123.456700"), STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1,234.567000"), STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12,345.670000"), STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123,456.700000"), STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1,234,567.000000"), STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12,345,670.000000"), STR("{:.6Lf}"), F(1.234567e7)); + test(STR("123,456,700,000,000,000,000.000000"), STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0.000001"), STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0.000012"), STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0.000123"), STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0.001235"), STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0.012346"), STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0.123457"), STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1.234567"), STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-12.345670"), STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-123.456700"), STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1,234.567000"), STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12,345.670000"), STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123,456.700000"), STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1,234,567.000000"), STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12,345,670.000000"), STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-123,456,700,000,000,000,000.000000"), STR("{:.6Lf}"), F(-1.234567e20)); + } + + std::locale::global(loc); + test(STR("0#000001"), STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0#000012"), STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0#000123"), STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0#001235"), STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0#012346"), STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0#123457"), STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1#234567"), STR("{:.6Lf}"), F(1.234567e0)); + test(STR("1_2#345670"), STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("12_3#456700"), STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1_23_4#567000"), STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12_34_5#670000"), STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123_45_6#700000"), STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1_234_56_7#000000"), STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12_345_67_0#000000"), STR("{:.6Lf}"), F(1.234567e7)); + test(STR("1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0#000001"), STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0#000012"), STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0#000123"), STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0#001235"), STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0#012346"), STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0#123457"), STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1#234567"), STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-1_2#345670"), STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-12_3#456700"), STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1_23_4#567000"), STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12_34_5#670000"), STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123_45_6#700000"), STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1_234_56_7#000000"), STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12_345_67_0#000000"), STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), STR("{:.6Lf}"), F(-1.234567e20)); + } + + test(STR("0.000001"), en_US, STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0.000012"), en_US, STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0.000123"), en_US, STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0.001235"), en_US, STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0.012346"), en_US, STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0.123457"), en_US, STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1.234567"), en_US, STR("{:.6Lf}"), F(1.234567e0)); + test(STR("12.345670"), en_US, STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("123.456700"), en_US, STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1,234.567000"), en_US, STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12,345.670000"), en_US, STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123,456.700000"), en_US, STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1,234,567.000000"), en_US, STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12,345,670.000000"), en_US, STR("{:.6Lf}"), F(1.234567e7)); + test(STR("123,456,700,000,000,000,000.000000"), en_US, STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0.000001"), en_US, STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0.000012"), en_US, STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0.000123"), en_US, STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0.001235"), en_US, STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0.012346"), en_US, STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0.123457"), en_US, STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1.234567"), en_US, STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-12.345670"), en_US, STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-123.456700"), en_US, STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1,234.567000"), en_US, STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12,345.670000"), en_US, STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123,456.700000"), en_US, STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1,234,567.000000"), en_US, STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12,345,670.000000"), en_US, STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-123,456,700,000,000,000,000.000000"), en_US, STR("{:.6Lf}"), F(-1.234567e20)); + } + + std::locale::global(en_US); + test(STR("0#000001"), loc, STR("{:.6Lf}"), F(1.234567e-6)); + test(STR("0#000012"), loc, STR("{:.6Lf}"), F(1.234567e-5)); + test(STR("0#000123"), loc, STR("{:.6Lf}"), F(1.234567e-4)); + test(STR("0#001235"), loc, STR("{:.6Lf}"), F(1.234567e-3)); + test(STR("0#012346"), loc, STR("{:.6Lf}"), F(1.234567e-2)); + test(STR("0#123457"), loc, STR("{:.6Lf}"), F(1.234567e-1)); + test(STR("1#234567"), loc, STR("{:.6Lf}"), F(1.234567e0)); + test(STR("1_2#345670"), loc, STR("{:.6Lf}"), F(1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("12_3#456700"), loc, STR("{:.6Lf}"), F(1.234567e2)); + test(STR("1_23_4#567000"), loc, STR("{:.6Lf}"), F(1.234567e3)); + test(STR("12_34_5#670000"), loc, STR("{:.6Lf}"), F(1.234567e4)); + test(STR("123_45_6#700000"), loc, STR("{:.6Lf}"), F(1.234567e5)); + test(STR("1_234_56_7#000000"), loc, STR("{:.6Lf}"), F(1.234567e6)); + test(STR("12_345_67_0#000000"), loc, STR("{:.6Lf}"), F(1.234567e7)); + test(STR("1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), loc, STR("{:.6Lf}"), F(1.234567e20)); + } + test(STR("-0#000001"), loc, STR("{:.6Lf}"), F(-1.234567e-6)); + test(STR("-0#000012"), loc, STR("{:.6Lf}"), F(-1.234567e-5)); + test(STR("-0#000123"), loc, STR("{:.6Lf}"), F(-1.234567e-4)); + test(STR("-0#001235"), loc, STR("{:.6Lf}"), F(-1.234567e-3)); + test(STR("-0#012346"), loc, STR("{:.6Lf}"), F(-1.234567e-2)); + test(STR("-0#123457"), loc, STR("{:.6Lf}"), F(-1.234567e-1)); + test(STR("-1#234567"), loc, STR("{:.6Lf}"), F(-1.234567e0)); + test(STR("-1_2#345670"), loc, STR("{:.6Lf}"), F(-1.234567e1)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-12_3#456700"), loc, STR("{:.6Lf}"), F(-1.234567e2)); + test(STR("-1_23_4#567000"), loc, STR("{:.6Lf}"), F(-1.234567e3)); + test(STR("-12_34_5#670000"), loc, STR("{:.6Lf}"), F(-1.234567e4)); + test(STR("-123_45_6#700000"), loc, STR("{:.6Lf}"), F(-1.234567e5)); + test(STR("-1_234_56_7#000000"), loc, STR("{:.6Lf}"), F(-1.234567e6)); + test(STR("-12_345_67_0#000000"), loc, STR("{:.6Lf}"), F(-1.234567e7)); + test(STR("-1_2_3_4_5_6_7_0_0_0_0_0_0_00_000_00_0#000000"), loc, STR("{:.6Lf}"), F(-1.234567e20)); + } + + // *** Fill, align, zero padding *** + if constexpr (sizeof(F) > sizeof(float)) { + std::locale::global(en_US); + test(STR("1,234.567000$$$"), STR("{:$<15.6Lf}"), F(1.234567e3)); + test(STR("$$$1,234.567000"), STR("{:$>15.6Lf}"), F(1.234567e3)); + test(STR("$1,234.567000$$"), STR("{:$^15.6Lf}"), F(1.234567e3)); + test(STR("0001,234.567000"), STR("{:015.6Lf}"), F(1.234567e3)); + test(STR("-1,234.567000$$$"), STR("{:$<16.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1,234.567000"), STR("{:$>16.6Lf}"), F(-1.234567e3)); + test(STR("$-1,234.567000$$"), STR("{:$^16.6Lf}"), F(-1.234567e3)); + test(STR("-0001,234.567000"), STR("{:016.6Lf}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1_23_4#567000$$$"), STR("{:$<16.6Lf}"), F(1.234567e3)); + test(STR("$$$1_23_4#567000"), STR("{:$>16.6Lf}"), F(1.234567e3)); + test(STR("$1_23_4#567000$$"), STR("{:$^16.6Lf}"), F(1.234567e3)); + test(STR("0001_23_4#567000"), STR("{:016.6Lf}"), F(1.234567e3)); + test(STR("-1_23_4#567000$$$"), STR("{:$<17.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#567000"), STR("{:$>17.6Lf}"), F(-1.234567e3)); + test(STR("$-1_23_4#567000$$"), STR("{:$^17.6Lf}"), F(-1.234567e3)); + test(STR("-0001_23_4#567000"), STR("{:017.6Lf}"), F(-1.234567e3)); + + test(STR("1,234.567000$$$"), en_US, STR("{:$<15.6Lf}"), F(1.234567e3)); + test(STR("$$$1,234.567000"), en_US, STR("{:$>15.6Lf}"), F(1.234567e3)); + test(STR("$1,234.567000$$"), en_US, STR("{:$^15.6Lf}"), F(1.234567e3)); + test(STR("0001,234.567000"), en_US, STR("{:015.6Lf}"), F(1.234567e3)); + test(STR("-1,234.567000$$$"), en_US, STR("{:$<16.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1,234.567000"), en_US, STR("{:$>16.6Lf}"), F(-1.234567e3)); + test(STR("$-1,234.567000$$"), en_US, STR("{:$^16.6Lf}"), F(-1.234567e3)); + test(STR("-0001,234.567000"), en_US, STR("{:016.6Lf}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1_23_4#567000$$$"), loc, STR("{:$<16.6Lf}"), F(1.234567e3)); + test(STR("$$$1_23_4#567000"), loc, STR("{:$>16.6Lf}"), F(1.234567e3)); + test(STR("$1_23_4#567000$$"), loc, STR("{:$^16.6Lf}"), F(1.234567e3)); + test(STR("0001_23_4#567000"), loc, STR("{:016.6Lf}"), F(1.234567e3)); + test(STR("-1_23_4#567000$$$"), loc, STR("{:$<17.6Lf}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#567000"), loc, STR("{:$>17.6Lf}"), F(-1.234567e3)); + test(STR("$-1_23_4#567000$$"), loc, STR("{:$^17.6Lf}"), F(-1.234567e3)); + test(STR("-0001_23_4#567000"), loc, STR("{:017.6Lf}"), F(-1.234567e3)); + } +} + +template +void test_floating_point_general_lower_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.23457e-06"), STR("{:.6Lg}"), F(1.234567e-6)); + test(STR("1.23457e-05"), STR("{:.6Lg}"), F(1.234567e-5)); + test(STR("0.000123457"), STR("{:.6Lg}"), F(1.234567e-4)); + test(STR("0.00123457"), STR("{:.6Lg}"), F(1.234567e-3)); + test(STR("0.0123457"), STR("{:.6Lg}"), F(1.234567e-2)); + test(STR("0.123457"), STR("{:.6Lg}"), F(1.234567e-1)); + test(STR("1.23457"), STR("{:.6Lg}"), F(1.234567e0)); + test(STR("12.3457"), STR("{:.6Lg}"), F(1.234567e1)); + test(STR("123.457"), STR("{:.6Lg}"), F(1.234567e2)); + test(STR("1,234.57"), STR("{:.6Lg}"), F(1.234567e3)); + test(STR("12,345.7"), STR("{:.6Lg}"), F(1.234567e4)); + test(STR("123,457"), STR("{:.6Lg}"), F(1.234567e5)); + test(STR("1.23457e+06"), STR("{:.6Lg}"), F(1.234567e6)); + test(STR("1.23457e+07"), STR("{:.6Lg}"), F(1.234567e7)); + test(STR("-1.23457e-06"), STR("{:.6Lg}"), F(-1.234567e-6)); + test(STR("-1.23457e-05"), STR("{:.6Lg}"), F(-1.234567e-5)); + test(STR("-0.000123457"), STR("{:.6Lg}"), F(-1.234567e-4)); + test(STR("-0.00123457"), STR("{:.6Lg}"), F(-1.234567e-3)); + test(STR("-0.0123457"), STR("{:.6Lg}"), F(-1.234567e-2)); + test(STR("-0.123457"), STR("{:.6Lg}"), F(-1.234567e-1)); + test(STR("-1.23457"), STR("{:.6Lg}"), F(-1.234567e0)); + test(STR("-12.3457"), STR("{:.6Lg}"), F(-1.234567e1)); + test(STR("-123.457"), STR("{:.6Lg}"), F(-1.234567e2)); + test(STR("-1,234.57"), STR("{:.6Lg}"), F(-1.234567e3)); + test(STR("-12,345.7"), STR("{:.6Lg}"), F(-1.234567e4)); + test(STR("-123,457"), STR("{:.6Lg}"), F(-1.234567e5)); + test(STR("-1.23457e+06"), STR("{:.6Lg}"), F(-1.234567e6)); + test(STR("-1.23457e+07"), STR("{:.6Lg}"), F(-1.234567e7)); + + std::locale::global(loc); + test(STR("1#23457e-06"), STR("{:.6Lg}"), F(1.234567e-6)); + test(STR("1#23457e-05"), STR("{:.6Lg}"), F(1.234567e-5)); + test(STR("0#000123457"), STR("{:.6Lg}"), F(1.234567e-4)); + test(STR("0#00123457"), STR("{:.6Lg}"), F(1.234567e-3)); + test(STR("0#0123457"), STR("{:.6Lg}"), F(1.234567e-2)); + test(STR("0#123457"), STR("{:.6Lg}"), F(1.234567e-1)); + test(STR("1#23457"), STR("{:.6Lg}"), F(1.234567e0)); + test(STR("1_2#3457"), STR("{:.6Lg}"), F(1.234567e1)); + test(STR("12_3#457"), STR("{:.6Lg}"), F(1.234567e2)); + test(STR("1_23_4#57"), STR("{:.6Lg}"), F(1.234567e3)); + test(STR("12_34_5#7"), STR("{:.6Lg}"), F(1.234567e4)); + test(STR("123_45_7"), STR("{:.6Lg}"), F(1.234567e5)); + test(STR("1#23457e+06"), STR("{:.6Lg}"), F(1.234567e6)); + test(STR("1#23457e+07"), STR("{:.6Lg}"), F(1.234567e7)); + test(STR("-1#23457e-06"), STR("{:.6Lg}"), F(-1.234567e-6)); + test(STR("-1#23457e-05"), STR("{:.6Lg}"), F(-1.234567e-5)); + test(STR("-0#000123457"), STR("{:.6Lg}"), F(-1.234567e-4)); + test(STR("-0#00123457"), STR("{:.6Lg}"), F(-1.234567e-3)); + test(STR("-0#0123457"), STR("{:.6Lg}"), F(-1.234567e-2)); + test(STR("-0#123457"), STR("{:.6Lg}"), F(-1.234567e-1)); + test(STR("-1#23457"), STR("{:.6Lg}"), F(-1.234567e0)); + test(STR("-1_2#3457"), STR("{:.6Lg}"), F(-1.234567e1)); + test(STR("-12_3#457"), STR("{:.6Lg}"), F(-1.234567e2)); + test(STR("-1_23_4#57"), STR("{:.6Lg}"), F(-1.234567e3)); + test(STR("-12_34_5#7"), STR("{:.6Lg}"), F(-1.234567e4)); + test(STR("-123_45_7"), STR("{:.6Lg}"), F(-1.234567e5)); + test(STR("-1#23457e+06"), STR("{:.6Lg}"), F(-1.234567e6)); + test(STR("-1#23457e+07"), STR("{:.6Lg}"), F(-1.234567e7)); + + test(STR("1.23457e-06"), en_US, STR("{:.6Lg}"), F(1.234567e-6)); + test(STR("1.23457e-05"), en_US, STR("{:.6Lg}"), F(1.234567e-5)); + test(STR("0.000123457"), en_US, STR("{:.6Lg}"), F(1.234567e-4)); + test(STR("0.00123457"), en_US, STR("{:.6Lg}"), F(1.234567e-3)); + test(STR("0.0123457"), en_US, STR("{:.6Lg}"), F(1.234567e-2)); + test(STR("0.123457"), en_US, STR("{:.6Lg}"), F(1.234567e-1)); + test(STR("1.23457"), en_US, STR("{:.6Lg}"), F(1.234567e0)); + test(STR("12.3457"), en_US, STR("{:.6Lg}"), F(1.234567e1)); + test(STR("123.457"), en_US, STR("{:.6Lg}"), F(1.234567e2)); + test(STR("1,234.57"), en_US, STR("{:.6Lg}"), F(1.234567e3)); + test(STR("12,345.7"), en_US, STR("{:.6Lg}"), F(1.234567e4)); + test(STR("123,457"), en_US, STR("{:.6Lg}"), F(1.234567e5)); + test(STR("1.23457e+06"), en_US, STR("{:.6Lg}"), F(1.234567e6)); + test(STR("1.23457e+07"), en_US, STR("{:.6Lg}"), F(1.234567e7)); + test(STR("-1.23457e-06"), en_US, STR("{:.6Lg}"), F(-1.234567e-6)); + test(STR("-1.23457e-05"), en_US, STR("{:.6Lg}"), F(-1.234567e-5)); + test(STR("-0.000123457"), en_US, STR("{:.6Lg}"), F(-1.234567e-4)); + test(STR("-0.00123457"), en_US, STR("{:.6Lg}"), F(-1.234567e-3)); + test(STR("-0.0123457"), en_US, STR("{:.6Lg}"), F(-1.234567e-2)); + test(STR("-0.123457"), en_US, STR("{:.6Lg}"), F(-1.234567e-1)); + test(STR("-1.23457"), en_US, STR("{:.6Lg}"), F(-1.234567e0)); + test(STR("-12.3457"), en_US, STR("{:.6Lg}"), F(-1.234567e1)); + test(STR("-123.457"), en_US, STR("{:.6Lg}"), F(-1.234567e2)); + test(STR("-1,234.57"), en_US, STR("{:.6Lg}"), F(-1.234567e3)); + test(STR("-12,345.7"), en_US, STR("{:.6Lg}"), F(-1.234567e4)); + test(STR("-123,457"), en_US, STR("{:.6Lg}"), F(-1.234567e5)); + test(STR("-1.23457e+06"), en_US, STR("{:.6Lg}"), F(-1.234567e6)); + test(STR("-1.23457e+07"), en_US, STR("{:.6Lg}"), F(-1.234567e7)); + + std::locale::global(en_US); + test(STR("1#23457e-06"), loc, STR("{:.6Lg}"), F(1.234567e-6)); + test(STR("1#23457e-05"), loc, STR("{:.6Lg}"), F(1.234567e-5)); + test(STR("0#000123457"), loc, STR("{:.6Lg}"), F(1.234567e-4)); + test(STR("0#00123457"), loc, STR("{:.6Lg}"), F(1.234567e-3)); + test(STR("0#0123457"), loc, STR("{:.6Lg}"), F(1.234567e-2)); + test(STR("0#123457"), loc, STR("{:.6Lg}"), F(1.234567e-1)); + test(STR("1#23457"), loc, STR("{:.6Lg}"), F(1.234567e0)); + test(STR("1_2#3457"), loc, STR("{:.6Lg}"), F(1.234567e1)); + test(STR("12_3#457"), loc, STR("{:.6Lg}"), F(1.234567e2)); + test(STR("1_23_4#57"), loc, STR("{:.6Lg}"), F(1.234567e3)); + test(STR("12_34_5#7"), loc, STR("{:.6Lg}"), F(1.234567e4)); + test(STR("123_45_7"), loc, STR("{:.6Lg}"), F(1.234567e5)); + test(STR("1#23457e+06"), loc, STR("{:.6Lg}"), F(1.234567e6)); + test(STR("1#23457e+07"), loc, STR("{:.6Lg}"), F(1.234567e7)); + test(STR("-1#23457e-06"), loc, STR("{:.6Lg}"), F(-1.234567e-6)); + test(STR("-1#23457e-05"), loc, STR("{:.6Lg}"), F(-1.234567e-5)); + test(STR("-0#000123457"), loc, STR("{:.6Lg}"), F(-1.234567e-4)); + test(STR("-0#00123457"), loc, STR("{:.6Lg}"), F(-1.234567e-3)); + test(STR("-0#0123457"), loc, STR("{:.6Lg}"), F(-1.234567e-2)); + test(STR("-0#123457"), loc, STR("{:.6Lg}"), F(-1.234567e-1)); + test(STR("-1#23457"), loc, STR("{:.6Lg}"), F(-1.234567e0)); + test(STR("-1_2#3457"), loc, STR("{:.6Lg}"), F(-1.234567e1)); + test(STR("-12_3#457"), loc, STR("{:.6Lg}"), F(-1.234567e2)); + test(STR("-1_23_4#57"), loc, STR("{:.6Lg}"), F(-1.234567e3)); + test(STR("-12_34_5#7"), loc, STR("{:.6Lg}"), F(-1.234567e4)); + test(STR("-123_45_7"), loc, STR("{:.6Lg}"), F(-1.234567e5)); + test(STR("-1#23457e+06"), loc, STR("{:.6Lg}"), F(-1.234567e6)); + test(STR("-1#23457e+07"), loc, STR("{:.6Lg}"), F(-1.234567e7)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1,234.57$$$"), STR("{:$<11.6Lg}"), F(1.234567e3)); + test(STR("$$$1,234.57"), STR("{:$>11.6Lg}"), F(1.234567e3)); + test(STR("$1,234.57$$"), STR("{:$^11.6Lg}"), F(1.234567e3)); + test(STR("0001,234.57"), STR("{:011.6Lg}"), F(1.234567e3)); + test(STR("-1,234.57$$$"), STR("{:$<12.6Lg}"), F(-1.234567e3)); + test(STR("$$$-1,234.57"), STR("{:$>12.6Lg}"), F(-1.234567e3)); + test(STR("$-1,234.57$$"), STR("{:$^12.6Lg}"), F(-1.234567e3)); + test(STR("-0001,234.57"), STR("{:012.6Lg}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1_23_4#57$$$"), STR("{:$<12.6Lg}"), F(1.234567e3)); + test(STR("$$$1_23_4#57"), STR("{:$>12.6Lg}"), F(1.234567e3)); + test(STR("$1_23_4#57$$"), STR("{:$^12.6Lg}"), F(1.234567e3)); + test(STR("0001_23_4#57"), STR("{:012.6Lg}"), F(1.234567e3)); + test(STR("-1_23_4#57$$$"), STR("{:$<13.6Lg}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#57"), STR("{:$>13.6Lg}"), F(-1.234567e3)); + test(STR("$-1_23_4#57$$"), STR("{:$^13.6Lg}"), F(-1.234567e3)); + test(STR("-0001_23_4#57"), STR("{:013.6Lg}"), F(-1.234567e3)); + + test(STR("1,234.57$$$"), en_US, STR("{:$<11.6Lg}"), F(1.234567e3)); + test(STR("$$$1,234.57"), en_US, STR("{:$>11.6Lg}"), F(1.234567e3)); + test(STR("$1,234.57$$"), en_US, STR("{:$^11.6Lg}"), F(1.234567e3)); + test(STR("0001,234.57"), en_US, STR("{:011.6Lg}"), F(1.234567e3)); + test(STR("-1,234.57$$$"), en_US, STR("{:$<12.6Lg}"), F(-1.234567e3)); + test(STR("$$$-1,234.57"), en_US, STR("{:$>12.6Lg}"), F(-1.234567e3)); + test(STR("$-1,234.57$$"), en_US, STR("{:$^12.6Lg}"), F(-1.234567e3)); + test(STR("-0001,234.57"), en_US, STR("{:012.6Lg}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1_23_4#57$$$"), loc, STR("{:$<12.6Lg}"), F(1.234567e3)); + test(STR("$$$1_23_4#57"), loc, STR("{:$>12.6Lg}"), F(1.234567e3)); + test(STR("$1_23_4#57$$"), loc, STR("{:$^12.6Lg}"), F(1.234567e3)); + test(STR("0001_23_4#57"), loc, STR("{:012.6Lg}"), F(1.234567e3)); + test(STR("-1_23_4#57$$$"), loc, STR("{:$<13.6Lg}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#57"), loc, STR("{:$>13.6Lg}"), F(-1.234567e3)); + test(STR("$-1_23_4#57$$"), loc, STR("{:$^13.6Lg}"), F(-1.234567e3)); + test(STR("-0001_23_4#57"), loc, STR("{:013.6Lg}"), F(-1.234567e3)); +} + +template +void test_floating_point_general_upper_case() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.23457E-06"), STR("{:.6LG}"), F(1.234567e-6)); + test(STR("1.23457E-05"), STR("{:.6LG}"), F(1.234567e-5)); + test(STR("0.000123457"), STR("{:.6LG}"), F(1.234567e-4)); + test(STR("0.00123457"), STR("{:.6LG}"), F(1.234567e-3)); + test(STR("0.0123457"), STR("{:.6LG}"), F(1.234567e-2)); + test(STR("0.123457"), STR("{:.6LG}"), F(1.234567e-1)); + test(STR("1.23457"), STR("{:.6LG}"), F(1.234567e0)); + test(STR("12.3457"), STR("{:.6LG}"), F(1.234567e1)); + test(STR("123.457"), STR("{:.6LG}"), F(1.234567e2)); + test(STR("1,234.57"), STR("{:.6LG}"), F(1.234567e3)); + test(STR("12,345.7"), STR("{:.6LG}"), F(1.234567e4)); + test(STR("123,457"), STR("{:.6LG}"), F(1.234567e5)); + test(STR("1.23457E+06"), STR("{:.6LG}"), F(1.234567e6)); + test(STR("1.23457E+07"), STR("{:.6LG}"), F(1.234567e7)); + test(STR("-1.23457E-06"), STR("{:.6LG}"), F(-1.234567e-6)); + test(STR("-1.23457E-05"), STR("{:.6LG}"), F(-1.234567e-5)); + test(STR("-0.000123457"), STR("{:.6LG}"), F(-1.234567e-4)); + test(STR("-0.00123457"), STR("{:.6LG}"), F(-1.234567e-3)); + test(STR("-0.0123457"), STR("{:.6LG}"), F(-1.234567e-2)); + test(STR("-0.123457"), STR("{:.6LG}"), F(-1.234567e-1)); + test(STR("-1.23457"), STR("{:.6LG}"), F(-1.234567e0)); + test(STR("-12.3457"), STR("{:.6LG}"), F(-1.234567e1)); + test(STR("-123.457"), STR("{:.6LG}"), F(-1.234567e2)); + test(STR("-1,234.57"), STR("{:.6LG}"), F(-1.234567e3)); + test(STR("-12,345.7"), STR("{:.6LG}"), F(-1.234567e4)); + test(STR("-123,457"), STR("{:.6LG}"), F(-1.234567e5)); + test(STR("-1.23457E+06"), STR("{:.6LG}"), F(-1.234567e6)); + test(STR("-1.23457E+07"), STR("{:.6LG}"), F(-1.234567e7)); + + std::locale::global(loc); + test(STR("1#23457E-06"), STR("{:.6LG}"), F(1.234567e-6)); + test(STR("1#23457E-05"), STR("{:.6LG}"), F(1.234567e-5)); + test(STR("0#000123457"), STR("{:.6LG}"), F(1.234567e-4)); + test(STR("0#00123457"), STR("{:.6LG}"), F(1.234567e-3)); + test(STR("0#0123457"), STR("{:.6LG}"), F(1.234567e-2)); + test(STR("0#123457"), STR("{:.6LG}"), F(1.234567e-1)); + test(STR("1#23457"), STR("{:.6LG}"), F(1.234567e0)); + test(STR("1_2#3457"), STR("{:.6LG}"), F(1.234567e1)); + test(STR("12_3#457"), STR("{:.6LG}"), F(1.234567e2)); + test(STR("1_23_4#57"), STR("{:.6LG}"), F(1.234567e3)); + test(STR("12_34_5#7"), STR("{:.6LG}"), F(1.234567e4)); + test(STR("123_45_7"), STR("{:.6LG}"), F(1.234567e5)); + test(STR("1#23457E+06"), STR("{:.6LG}"), F(1.234567e6)); + test(STR("1#23457E+07"), STR("{:.6LG}"), F(1.234567e7)); + test(STR("-1#23457E-06"), STR("{:.6LG}"), F(-1.234567e-6)); + test(STR("-1#23457E-05"), STR("{:.6LG}"), F(-1.234567e-5)); + test(STR("-0#000123457"), STR("{:.6LG}"), F(-1.234567e-4)); + test(STR("-0#00123457"), STR("{:.6LG}"), F(-1.234567e-3)); + test(STR("-0#0123457"), STR("{:.6LG}"), F(-1.234567e-2)); + test(STR("-0#123457"), STR("{:.6LG}"), F(-1.234567e-1)); + test(STR("-1#23457"), STR("{:.6LG}"), F(-1.234567e0)); + test(STR("-1_2#3457"), STR("{:.6LG}"), F(-1.234567e1)); + test(STR("-12_3#457"), STR("{:.6LG}"), F(-1.234567e2)); + test(STR("-1_23_4#57"), STR("{:.6LG}"), F(-1.234567e3)); + test(STR("-12_34_5#7"), STR("{:.6LG}"), F(-1.234567e4)); + test(STR("-123_45_7"), STR("{:.6LG}"), F(-1.234567e5)); + test(STR("-1#23457E+06"), STR("{:.6LG}"), F(-1.234567e6)); + test(STR("-1#23457E+07"), STR("{:.6LG}"), F(-1.234567e7)); + + test(STR("1.23457E-06"), en_US, STR("{:.6LG}"), F(1.234567e-6)); + test(STR("1.23457E-05"), en_US, STR("{:.6LG}"), F(1.234567e-5)); + test(STR("0.000123457"), en_US, STR("{:.6LG}"), F(1.234567e-4)); + test(STR("0.00123457"), en_US, STR("{:.6LG}"), F(1.234567e-3)); + test(STR("0.0123457"), en_US, STR("{:.6LG}"), F(1.234567e-2)); + test(STR("0.123457"), en_US, STR("{:.6LG}"), F(1.234567e-1)); + test(STR("1.23457"), en_US, STR("{:.6LG}"), F(1.234567e0)); + test(STR("12.3457"), en_US, STR("{:.6LG}"), F(1.234567e1)); + test(STR("123.457"), en_US, STR("{:.6LG}"), F(1.234567e2)); + test(STR("1,234.57"), en_US, STR("{:.6LG}"), F(1.234567e3)); + test(STR("12,345.7"), en_US, STR("{:.6LG}"), F(1.234567e4)); + test(STR("123,457"), en_US, STR("{:.6LG}"), F(1.234567e5)); + test(STR("1.23457E+06"), en_US, STR("{:.6LG}"), F(1.234567e6)); + test(STR("1.23457E+07"), en_US, STR("{:.6LG}"), F(1.234567e7)); + test(STR("-1.23457E-06"), en_US, STR("{:.6LG}"), F(-1.234567e-6)); + test(STR("-1.23457E-05"), en_US, STR("{:.6LG}"), F(-1.234567e-5)); + test(STR("-0.000123457"), en_US, STR("{:.6LG}"), F(-1.234567e-4)); + test(STR("-0.00123457"), en_US, STR("{:.6LG}"), F(-1.234567e-3)); + test(STR("-0.0123457"), en_US, STR("{:.6LG}"), F(-1.234567e-2)); + test(STR("-0.123457"), en_US, STR("{:.6LG}"), F(-1.234567e-1)); + test(STR("-1.23457"), en_US, STR("{:.6LG}"), F(-1.234567e0)); + test(STR("-12.3457"), en_US, STR("{:.6LG}"), F(-1.234567e1)); + test(STR("-123.457"), en_US, STR("{:.6LG}"), F(-1.234567e2)); + test(STR("-1,234.57"), en_US, STR("{:.6LG}"), F(-1.234567e3)); + test(STR("-12,345.7"), en_US, STR("{:.6LG}"), F(-1.234567e4)); + test(STR("-123,457"), en_US, STR("{:.6LG}"), F(-1.234567e5)); + test(STR("-1.23457E+06"), en_US, STR("{:.6LG}"), F(-1.234567e6)); + test(STR("-1.23457E+07"), en_US, STR("{:.6LG}"), F(-1.234567e7)); + + std::locale::global(en_US); + test(STR("1#23457E-06"), loc, STR("{:.6LG}"), F(1.234567e-6)); + test(STR("1#23457E-05"), loc, STR("{:.6LG}"), F(1.234567e-5)); + test(STR("0#000123457"), loc, STR("{:.6LG}"), F(1.234567e-4)); + test(STR("0#00123457"), loc, STR("{:.6LG}"), F(1.234567e-3)); + test(STR("0#0123457"), loc, STR("{:.6LG}"), F(1.234567e-2)); + test(STR("0#123457"), loc, STR("{:.6LG}"), F(1.234567e-1)); + test(STR("1#23457"), loc, STR("{:.6LG}"), F(1.234567e0)); + test(STR("1_2#3457"), loc, STR("{:.6LG}"), F(1.234567e1)); + test(STR("12_3#457"), loc, STR("{:.6LG}"), F(1.234567e2)); + test(STR("1_23_4#57"), loc, STR("{:.6LG}"), F(1.234567e3)); + test(STR("12_34_5#7"), loc, STR("{:.6LG}"), F(1.234567e4)); + test(STR("123_45_7"), loc, STR("{:.6LG}"), F(1.234567e5)); + test(STR("1#23457E+06"), loc, STR("{:.6LG}"), F(1.234567e6)); + test(STR("1#23457E+07"), loc, STR("{:.6LG}"), F(1.234567e7)); + test(STR("-1#23457E-06"), loc, STR("{:.6LG}"), F(-1.234567e-6)); + test(STR("-1#23457E-05"), loc, STR("{:.6LG}"), F(-1.234567e-5)); + test(STR("-0#000123457"), loc, STR("{:.6LG}"), F(-1.234567e-4)); + test(STR("-0#00123457"), loc, STR("{:.6LG}"), F(-1.234567e-3)); + test(STR("-0#0123457"), loc, STR("{:.6LG}"), F(-1.234567e-2)); + test(STR("-0#123457"), loc, STR("{:.6LG}"), F(-1.234567e-1)); + test(STR("-1#23457"), loc, STR("{:.6LG}"), F(-1.234567e0)); + test(STR("-1_2#3457"), loc, STR("{:.6LG}"), F(-1.234567e1)); + test(STR("-12_3#457"), loc, STR("{:.6LG}"), F(-1.234567e2)); + test(STR("-1_23_4#57"), loc, STR("{:.6LG}"), F(-1.234567e3)); + test(STR("-12_34_5#7"), loc, STR("{:.6LG}"), F(-1.234567e4)); + test(STR("-123_45_7"), loc, STR("{:.6LG}"), F(-1.234567e5)); + test(STR("-1#23457E+06"), loc, STR("{:.6LG}"), F(-1.234567e6)); + test(STR("-1#23457E+07"), loc, STR("{:.6LG}"), F(-1.234567e7)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1,234.57$$$"), STR("{:$<11.6LG}"), F(1.234567e3)); + test(STR("$$$1,234.57"), STR("{:$>11.6LG}"), F(1.234567e3)); + test(STR("$1,234.57$$"), STR("{:$^11.6LG}"), F(1.234567e3)); + test(STR("0001,234.57"), STR("{:011.6LG}"), F(1.234567e3)); + test(STR("-1,234.57$$$"), STR("{:$<12.6LG}"), F(-1.234567e3)); + test(STR("$$$-1,234.57"), STR("{:$>12.6LG}"), F(-1.234567e3)); + test(STR("$-1,234.57$$"), STR("{:$^12.6LG}"), F(-1.234567e3)); + test(STR("-0001,234.57"), STR("{:012.6LG}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1_23_4#57$$$"), STR("{:$<12.6LG}"), F(1.234567e3)); + test(STR("$$$1_23_4#57"), STR("{:$>12.6LG}"), F(1.234567e3)); + test(STR("$1_23_4#57$$"), STR("{:$^12.6LG}"), F(1.234567e3)); + test(STR("0001_23_4#57"), STR("{:012.6LG}"), F(1.234567e3)); + test(STR("-1_23_4#57$$$"), STR("{:$<13.6LG}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#57"), STR("{:$>13.6LG}"), F(-1.234567e3)); + test(STR("$-1_23_4#57$$"), STR("{:$^13.6LG}"), F(-1.234567e3)); + test(STR("-0001_23_4#57"), STR("{:013.6LG}"), F(-1.234567e3)); + + test(STR("1,234.57$$$"), en_US, STR("{:$<11.6LG}"), F(1.234567e3)); + test(STR("$$$1,234.57"), en_US, STR("{:$>11.6LG}"), F(1.234567e3)); + test(STR("$1,234.57$$"), en_US, STR("{:$^11.6LG}"), F(1.234567e3)); + test(STR("0001,234.57"), en_US, STR("{:011.6LG}"), F(1.234567e3)); + test(STR("-1,234.57$$$"), en_US, STR("{:$<12.6LG}"), F(-1.234567e3)); + test(STR("$$$-1,234.57"), en_US, STR("{:$>12.6LG}"), F(-1.234567e3)); + test(STR("$-1,234.57$$"), en_US, STR("{:$^12.6LG}"), F(-1.234567e3)); + test(STR("-0001,234.57"), en_US, STR("{:012.6LG}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1_23_4#57$$$"), loc, STR("{:$<12.6LG}"), F(1.234567e3)); + test(STR("$$$1_23_4#57"), loc, STR("{:$>12.6LG}"), F(1.234567e3)); + test(STR("$1_23_4#57$$"), loc, STR("{:$^12.6LG}"), F(1.234567e3)); + test(STR("0001_23_4#57"), loc, STR("{:012.6LG}"), F(1.234567e3)); + test(STR("-1_23_4#57$$$"), loc, STR("{:$<13.6LG}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#57"), loc, STR("{:$>13.6LG}"), F(-1.234567e3)); + test(STR("$-1_23_4#57$$"), loc, STR("{:$^13.6LG}"), F(-1.234567e3)); + test(STR("-0001_23_4#57"), loc, STR("{:013.6LG}"), F(-1.234567e3)); +} + +template +void test_floating_point_default() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.234567e-06"), STR("{:L}"), F(1.234567e-6)); + test(STR("1.234567e-05"), STR("{:L}"), F(1.234567e-5)); + test(STR("0.0001234567"), STR("{:L}"), F(1.234567e-4)); + test(STR("0.001234567"), STR("{:L}"), F(1.234567e-3)); + test(STR("0.01234567"), STR("{:L}"), F(1.234567e-2)); + test(STR("0.1234567"), STR("{:L}"), F(1.234567e-1)); + test(STR("1.234567"), STR("{:L}"), F(1.234567e0)); + test(STR("12.34567"), STR("{:L}"), F(1.234567e1)); + test(STR("123.4567"), STR("{:L}"), F(1.234567e2)); + test(STR("1,234.567"), STR("{:L}"), F(1.234567e3)); + test(STR("12,345.67"), STR("{:L}"), F(1.234567e4)); + test(STR("123,456.7"), STR("{:L}"), F(1.234567e5)); + test(STR("1,234,567"), STR("{:L}"), F(1.234567e6)); + test(STR("12,345,670"), STR("{:L}"), F(1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("123,456,700"), STR("{:L}"), F(1.234567e8)); + test(STR("1,234,567,000"), STR("{:L}"), F(1.234567e9)); + test(STR("12,345,670,000"), STR("{:L}"), F(1.234567e10)); + test(STR("123,456,700,000"), STR("{:L}"), F(1.234567e11)); + test(STR("1.234567e+12"), STR("{:L}"), F(1.234567e12)); + test(STR("1.234567e+13"), STR("{:L}"), F(1.234567e13)); + } + test(STR("-1.234567e-06"), STR("{:L}"), F(-1.234567e-6)); + test(STR("-1.234567e-05"), STR("{:L}"), F(-1.234567e-5)); + test(STR("-0.0001234567"), STR("{:L}"), F(-1.234567e-4)); + test(STR("-0.001234567"), STR("{:L}"), F(-1.234567e-3)); + test(STR("-0.01234567"), STR("{:L}"), F(-1.234567e-2)); + test(STR("-0.1234567"), STR("{:L}"), F(-1.234567e-1)); + test(STR("-1.234567"), STR("{:L}"), F(-1.234567e0)); + test(STR("-12.34567"), STR("{:L}"), F(-1.234567e1)); + test(STR("-123.4567"), STR("{:L}"), F(-1.234567e2)); + test(STR("-1,234.567"), STR("{:L}"), F(-1.234567e3)); + test(STR("-12,345.67"), STR("{:L}"), F(-1.234567e4)); + test(STR("-123,456.7"), STR("{:L}"), F(-1.234567e5)); + test(STR("-1,234,567"), STR("{:L}"), F(-1.234567e6)); + test(STR("-12,345,670"), STR("{:L}"), F(-1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-123,456,700"), STR("{:L}"), F(-1.234567e8)); + test(STR("-1,234,567,000"), STR("{:L}"), F(-1.234567e9)); + test(STR("-12,345,670,000"), STR("{:L}"), F(-1.234567e10)); + test(STR("-123,456,700,000"), STR("{:L}"), F(-1.234567e11)); + test(STR("-1.234567e+12"), STR("{:L}"), F(-1.234567e12)); + test(STR("-1.234567e+13"), STR("{:L}"), F(-1.234567e13)); + } + + std::locale::global(loc); + test(STR("1#234567e-06"), STR("{:L}"), F(1.234567e-6)); + test(STR("1#234567e-05"), STR("{:L}"), F(1.234567e-5)); + test(STR("0#0001234567"), STR("{:L}"), F(1.234567e-4)); + test(STR("0#001234567"), STR("{:L}"), F(1.234567e-3)); + test(STR("0#01234567"), STR("{:L}"), F(1.234567e-2)); + test(STR("0#1234567"), STR("{:L}"), F(1.234567e-1)); + test(STR("1#234567"), STR("{:L}"), F(1.234567e0)); + test(STR("1_2#34567"), STR("{:L}"), F(1.234567e1)); + test(STR("12_3#4567"), STR("{:L}"), F(1.234567e2)); + test(STR("1_23_4#567"), STR("{:L}"), F(1.234567e3)); + test(STR("12_34_5#67"), STR("{:L}"), F(1.234567e4)); + test(STR("123_45_6#7"), STR("{:L}"), F(1.234567e5)); + test(STR("1_234_56_7"), STR("{:L}"), F(1.234567e6)); + test(STR("12_345_67_0"), STR("{:L}"), F(1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("1_23_456_70_0"), STR("{:L}"), F(1.234567e8)); + test(STR("1_2_34_567_00_0"), STR("{:L}"), F(1.234567e9)); + test(STR("1_2_3_45_670_00_0"), STR("{:L}"), F(1.234567e10)); + test(STR("1_2_3_4_56_700_00_0"), STR("{:L}"), F(1.234567e11)); + test(STR("1#234567e+12"), STR("{:L}"), F(1.234567e12)); + test(STR("1#234567e+13"), STR("{:L}"), F(1.234567e13)); + } + test(STR("-1#234567e-06"), STR("{:L}"), F(-1.234567e-6)); + test(STR("-1#234567e-05"), STR("{:L}"), F(-1.234567e-5)); + test(STR("-0#0001234567"), STR("{:L}"), F(-1.234567e-4)); + test(STR("-0#001234567"), STR("{:L}"), F(-1.234567e-3)); + test(STR("-0#01234567"), STR("{:L}"), F(-1.234567e-2)); + test(STR("-0#1234567"), STR("{:L}"), F(-1.234567e-1)); + test(STR("-1#234567"), STR("{:L}"), F(-1.234567e0)); + test(STR("-1_2#34567"), STR("{:L}"), F(-1.234567e1)); + test(STR("-12_3#4567"), STR("{:L}"), F(-1.234567e2)); + test(STR("-1_23_4#567"), STR("{:L}"), F(-1.234567e3)); + test(STR("-12_34_5#67"), STR("{:L}"), F(-1.234567e4)); + test(STR("-123_45_6#7"), STR("{:L}"), F(-1.234567e5)); + test(STR("-1_234_56_7"), STR("{:L}"), F(-1.234567e6)); + test(STR("-12_345_67_0"), STR("{:L}"), F(-1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-1_23_456_70_0"), STR("{:L}"), F(-1.234567e8)); + test(STR("-1_2_34_567_00_0"), STR("{:L}"), F(-1.234567e9)); + test(STR("-1_2_3_45_670_00_0"), STR("{:L}"), F(-1.234567e10)); + test(STR("-1_2_3_4_56_700_00_0"), STR("{:L}"), F(-1.234567e11)); + test(STR("-1#234567e+12"), STR("{:L}"), F(-1.234567e12)); + test(STR("-1#234567e+13"), STR("{:L}"), F(-1.234567e13)); + } + + test(STR("1.234567e-06"), en_US, STR("{:L}"), F(1.234567e-6)); + test(STR("1.234567e-05"), en_US, STR("{:L}"), F(1.234567e-5)); + test(STR("0.0001234567"), en_US, STR("{:L}"), F(1.234567e-4)); + test(STR("0.001234567"), en_US, STR("{:L}"), F(1.234567e-3)); + test(STR("0.01234567"), en_US, STR("{:L}"), F(1.234567e-2)); + test(STR("0.1234567"), en_US, STR("{:L}"), F(1.234567e-1)); + test(STR("1.234567"), en_US, STR("{:L}"), F(1.234567e0)); + test(STR("12.34567"), en_US, STR("{:L}"), F(1.234567e1)); + test(STR("123.4567"), en_US, STR("{:L}"), F(1.234567e2)); + test(STR("1,234.567"), en_US, STR("{:L}"), F(1.234567e3)); + test(STR("12,345.67"), en_US, STR("{:L}"), F(1.234567e4)); + test(STR("123,456.7"), en_US, STR("{:L}"), F(1.234567e5)); + test(STR("1,234,567"), en_US, STR("{:L}"), F(1.234567e6)); + test(STR("12,345,670"), en_US, STR("{:L}"), F(1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("123,456,700"), en_US, STR("{:L}"), F(1.234567e8)); + test(STR("1,234,567,000"), en_US, STR("{:L}"), F(1.234567e9)); + test(STR("12,345,670,000"), en_US, STR("{:L}"), F(1.234567e10)); + test(STR("123,456,700,000"), en_US, STR("{:L}"), F(1.234567e11)); + test(STR("1.234567e+12"), en_US, STR("{:L}"), F(1.234567e12)); + test(STR("1.234567e+13"), en_US, STR("{:L}"), F(1.234567e13)); + } + test(STR("-1.234567e-06"), en_US, STR("{:L}"), F(-1.234567e-6)); + test(STR("-1.234567e-05"), en_US, STR("{:L}"), F(-1.234567e-5)); + test(STR("-0.0001234567"), en_US, STR("{:L}"), F(-1.234567e-4)); + test(STR("-0.001234567"), en_US, STR("{:L}"), F(-1.234567e-3)); + test(STR("-0.01234567"), en_US, STR("{:L}"), F(-1.234567e-2)); + test(STR("-0.1234567"), en_US, STR("{:L}"), F(-1.234567e-1)); + test(STR("-1.234567"), en_US, STR("{:L}"), F(-1.234567e0)); + test(STR("-12.34567"), en_US, STR("{:L}"), F(-1.234567e1)); + test(STR("-123.4567"), en_US, STR("{:L}"), F(-1.234567e2)); + test(STR("-1,234.567"), en_US, STR("{:L}"), F(-1.234567e3)); + test(STR("-12,345.67"), en_US, STR("{:L}"), F(-1.234567e4)); + test(STR("-123,456.7"), en_US, STR("{:L}"), F(-1.234567e5)); + test(STR("-1,234,567"), en_US, STR("{:L}"), F(-1.234567e6)); + test(STR("-12,345,670"), en_US, STR("{:L}"), F(-1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-123,456,700"), en_US, STR("{:L}"), F(-1.234567e8)); + test(STR("-1,234,567,000"), en_US, STR("{:L}"), F(-1.234567e9)); + test(STR("-12,345,670,000"), en_US, STR("{:L}"), F(-1.234567e10)); + test(STR("-123,456,700,000"), en_US, STR("{:L}"), F(-1.234567e11)); + test(STR("-1.234567e+12"), en_US, STR("{:L}"), F(-1.234567e12)); + test(STR("-1.234567e+13"), en_US, STR("{:L}"), F(-1.234567e13)); + } + + std::locale::global(en_US); + test(STR("1#234567e-06"), loc, STR("{:L}"), F(1.234567e-6)); + test(STR("1#234567e-05"), loc, STR("{:L}"), F(1.234567e-5)); + test(STR("0#0001234567"), loc, STR("{:L}"), F(1.234567e-4)); + test(STR("0#001234567"), loc, STR("{:L}"), F(1.234567e-3)); + test(STR("0#01234567"), loc, STR("{:L}"), F(1.234567e-2)); + test(STR("0#1234567"), loc, STR("{:L}"), F(1.234567e-1)); + test(STR("1#234567"), loc, STR("{:L}"), F(1.234567e0)); + test(STR("1_2#34567"), loc, STR("{:L}"), F(1.234567e1)); + test(STR("12_3#4567"), loc, STR("{:L}"), F(1.234567e2)); + test(STR("1_23_4#567"), loc, STR("{:L}"), F(1.234567e3)); + test(STR("12_34_5#67"), loc, STR("{:L}"), F(1.234567e4)); + test(STR("123_45_6#7"), loc, STR("{:L}"), F(1.234567e5)); + test(STR("1_234_56_7"), loc, STR("{:L}"), F(1.234567e6)); + test(STR("12_345_67_0"), loc, STR("{:L}"), F(1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("1_23_456_70_0"), loc, STR("{:L}"), F(1.234567e8)); + test(STR("1_2_34_567_00_0"), loc, STR("{:L}"), F(1.234567e9)); + test(STR("1_2_3_45_670_00_0"), loc, STR("{:L}"), F(1.234567e10)); + test(STR("1_2_3_4_56_700_00_0"), loc, STR("{:L}"), F(1.234567e11)); + test(STR("1#234567e+12"), loc, STR("{:L}"), F(1.234567e12)); + test(STR("1#234567e+13"), loc, STR("{:L}"), F(1.234567e13)); + } + test(STR("-1#234567e-06"), loc, STR("{:L}"), F(-1.234567e-6)); + test(STR("-1#234567e-05"), loc, STR("{:L}"), F(-1.234567e-5)); + test(STR("-0#0001234567"), loc, STR("{:L}"), F(-1.234567e-4)); + test(STR("-0#001234567"), loc, STR("{:L}"), F(-1.234567e-3)); + test(STR("-0#01234567"), loc, STR("{:L}"), F(-1.234567e-2)); + test(STR("-0#1234567"), loc, STR("{:L}"), F(-1.234567e-1)); + test(STR("-1#234567"), loc, STR("{:L}"), F(-1.234567e0)); + test(STR("-1_2#34567"), loc, STR("{:L}"), F(-1.234567e1)); + test(STR("-12_3#4567"), loc, STR("{:L}"), F(-1.234567e2)); + test(STR("-1_23_4#567"), loc, STR("{:L}"), F(-1.234567e3)); + test(STR("-12_34_5#67"), loc, STR("{:L}"), F(-1.234567e4)); + test(STR("-123_45_6#7"), loc, STR("{:L}"), F(-1.234567e5)); + test(STR("-1_234_56_7"), loc, STR("{:L}"), F(-1.234567e6)); + test(STR("-12_345_67_0"), loc, STR("{:L}"), F(-1.234567e7)); + if constexpr (sizeof(F) > sizeof(float)) { + test(STR("-1_23_456_70_0"), loc, STR("{:L}"), F(-1.234567e8)); + test(STR("-1_2_34_567_00_0"), loc, STR("{:L}"), F(-1.234567e9)); + test(STR("-1_2_3_45_670_00_0"), loc, STR("{:L}"), F(-1.234567e10)); + test(STR("-1_2_3_4_56_700_00_0"), loc, STR("{:L}"), F(-1.234567e11)); + test(STR("-1#234567e+12"), loc, STR("{:L}"), F(-1.234567e12)); + test(STR("-1#234567e+13"), loc, STR("{:L}"), F(-1.234567e13)); + } + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1,234.567$$$"), STR("{:$<12L}"), F(1.234567e3)); + test(STR("$$$1,234.567"), STR("{:$>12L}"), F(1.234567e3)); + test(STR("$1,234.567$$"), STR("{:$^12L}"), F(1.234567e3)); + test(STR("0001,234.567"), STR("{:012L}"), F(1.234567e3)); + test(STR("-1,234.567$$$"), STR("{:$<13L}"), F(-1.234567e3)); + test(STR("$$$-1,234.567"), STR("{:$>13L}"), F(-1.234567e3)); + test(STR("$-1,234.567$$"), STR("{:$^13L}"), F(-1.234567e3)); + test(STR("-0001,234.567"), STR("{:013L}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1_23_4#567$$$"), STR("{:$<13L}"), F(1.234567e3)); + test(STR("$$$1_23_4#567"), STR("{:$>13L}"), F(1.234567e3)); + test(STR("$1_23_4#567$$"), STR("{:$^13L}"), F(1.234567e3)); + test(STR("0001_23_4#567"), STR("{:013L}"), F(1.234567e3)); + test(STR("-1_23_4#567$$$"), STR("{:$<14L}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#567"), STR("{:$>14L}"), F(-1.234567e3)); + test(STR("$-1_23_4#567$$"), STR("{:$^14L}"), F(-1.234567e3)); + test(STR("-0001_23_4#567"), STR("{:014L}"), F(-1.234567e3)); + + test(STR("1,234.567$$$"), en_US, STR("{:$<12L}"), F(1.234567e3)); + test(STR("$$$1,234.567"), en_US, STR("{:$>12L}"), F(1.234567e3)); + test(STR("$1,234.567$$"), en_US, STR("{:$^12L}"), F(1.234567e3)); + test(STR("0001,234.567"), en_US, STR("{:012L}"), F(1.234567e3)); + test(STR("-1,234.567$$$"), en_US, STR("{:$<13L}"), F(-1.234567e3)); + test(STR("$$$-1,234.567"), en_US, STR("{:$>13L}"), F(-1.234567e3)); + test(STR("$-1,234.567$$"), en_US, STR("{:$^13L}"), F(-1.234567e3)); + test(STR("-0001,234.567"), en_US, STR("{:013L}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1_23_4#567$$$"), loc, STR("{:$<13L}"), F(1.234567e3)); + test(STR("$$$1_23_4#567"), loc, STR("{:$>13L}"), F(1.234567e3)); + test(STR("$1_23_4#567$$"), loc, STR("{:$^13L}"), F(1.234567e3)); + test(STR("0001_23_4#567"), loc, STR("{:013L}"), F(1.234567e3)); + test(STR("-1_23_4#567$$$"), loc, STR("{:$<14L}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#567"), loc, STR("{:$>14L}"), F(-1.234567e3)); + test(STR("$-1_23_4#567$$"), loc, STR("{:$^14L}"), F(-1.234567e3)); + test(STR("-0001_23_4#567"), loc, STR("{:014L}"), F(-1.234567e3)); +} + +template +void test_floating_point_default_precision() { + std::locale loc = std::locale(std::locale(), new numpunct()); + std::locale en_US = std::locale(LOCALE_en_US_UTF_8); + + // *** Basic *** + std::locale::global(en_US); + test(STR("1.23457e-06"), STR("{:.6L}"), F(1.234567e-6)); + test(STR("1.23457e-05"), STR("{:.6L}"), F(1.234567e-5)); + test(STR("0.000123457"), STR("{:.6L}"), F(1.234567e-4)); + test(STR("0.00123457"), STR("{:.6L}"), F(1.234567e-3)); + test(STR("0.0123457"), STR("{:.6L}"), F(1.234567e-2)); + test(STR("0.123457"), STR("{:.6L}"), F(1.234567e-1)); + test(STR("1.23457"), STR("{:.6L}"), F(1.234567e0)); + test(STR("12.3457"), STR("{:.6L}"), F(1.234567e1)); + test(STR("123.457"), STR("{:.6L}"), F(1.234567e2)); + test(STR("1,234.57"), STR("{:.6L}"), F(1.234567e3)); + test(STR("12,345.7"), STR("{:.6L}"), F(1.234567e4)); + test(STR("123,457"), STR("{:.6L}"), F(1.234567e5)); + test(STR("1.23457e+06"), STR("{:.6L}"), F(1.234567e6)); + test(STR("1.23457e+07"), STR("{:.6L}"), F(1.234567e7)); + test(STR("-1.23457e-06"), STR("{:.6L}"), F(-1.234567e-6)); + test(STR("-1.23457e-05"), STR("{:.6L}"), F(-1.234567e-5)); + test(STR("-0.000123457"), STR("{:.6L}"), F(-1.234567e-4)); + test(STR("-0.00123457"), STR("{:.6L}"), F(-1.234567e-3)); + test(STR("-0.0123457"), STR("{:.6L}"), F(-1.234567e-2)); + test(STR("-0.123457"), STR("{:.6L}"), F(-1.234567e-1)); + test(STR("-1.23457"), STR("{:.6L}"), F(-1.234567e0)); + test(STR("-12.3457"), STR("{:.6L}"), F(-1.234567e1)); + test(STR("-123.457"), STR("{:.6L}"), F(-1.234567e2)); + test(STR("-1,234.57"), STR("{:.6L}"), F(-1.234567e3)); + test(STR("-12,345.7"), STR("{:.6L}"), F(-1.234567e4)); + test(STR("-123,457"), STR("{:.6L}"), F(-1.234567e5)); + test(STR("-1.23457e+06"), STR("{:.6L}"), F(-1.234567e6)); + test(STR("-1.23457e+07"), STR("{:.6L}"), F(-1.234567e7)); + + std::locale::global(loc); + test(STR("1#23457e-06"), STR("{:.6L}"), F(1.234567e-6)); + test(STR("1#23457e-05"), STR("{:.6L}"), F(1.234567e-5)); + test(STR("0#000123457"), STR("{:.6L}"), F(1.234567e-4)); + test(STR("0#00123457"), STR("{:.6L}"), F(1.234567e-3)); + test(STR("0#0123457"), STR("{:.6L}"), F(1.234567e-2)); + test(STR("0#123457"), STR("{:.6L}"), F(1.234567e-1)); + test(STR("1#23457"), STR("{:.6L}"), F(1.234567e0)); + test(STR("1_2#3457"), STR("{:.6L}"), F(1.234567e1)); + test(STR("12_3#457"), STR("{:.6L}"), F(1.234567e2)); + test(STR("1_23_4#57"), STR("{:.6L}"), F(1.234567e3)); + test(STR("12_34_5#7"), STR("{:.6L}"), F(1.234567e4)); + test(STR("123_45_7"), STR("{:.6L}"), F(1.234567e5)); + test(STR("1#23457e+06"), STR("{:.6L}"), F(1.234567e6)); + test(STR("1#23457e+07"), STR("{:.6L}"), F(1.234567e7)); + test(STR("-1#23457e-06"), STR("{:.6L}"), F(-1.234567e-6)); + test(STR("-1#23457e-05"), STR("{:.6L}"), F(-1.234567e-5)); + test(STR("-0#000123457"), STR("{:.6L}"), F(-1.234567e-4)); + test(STR("-0#00123457"), STR("{:.6L}"), F(-1.234567e-3)); + test(STR("-0#0123457"), STR("{:.6L}"), F(-1.234567e-2)); + test(STR("-0#123457"), STR("{:.6L}"), F(-1.234567e-1)); + test(STR("-1#23457"), STR("{:.6L}"), F(-1.234567e0)); + test(STR("-1_2#3457"), STR("{:.6L}"), F(-1.234567e1)); + test(STR("-12_3#457"), STR("{:.6L}"), F(-1.234567e2)); + test(STR("-1_23_4#57"), STR("{:.6L}"), F(-1.234567e3)); + test(STR("-12_34_5#7"), STR("{:.6L}"), F(-1.234567e4)); + test(STR("-123_45_7"), STR("{:.6L}"), F(-1.234567e5)); + test(STR("-1#23457e+06"), STR("{:.6L}"), F(-1.234567e6)); + test(STR("-1#23457e+07"), STR("{:.6L}"), F(-1.234567e7)); + + test(STR("1.23457e-06"), en_US, STR("{:.6L}"), F(1.234567e-6)); + test(STR("1.23457e-05"), en_US, STR("{:.6L}"), F(1.234567e-5)); + test(STR("0.000123457"), en_US, STR("{:.6L}"), F(1.234567e-4)); + test(STR("0.00123457"), en_US, STR("{:.6L}"), F(1.234567e-3)); + test(STR("0.0123457"), en_US, STR("{:.6L}"), F(1.234567e-2)); + test(STR("0.123457"), en_US, STR("{:.6L}"), F(1.234567e-1)); + test(STR("1.23457"), en_US, STR("{:.6L}"), F(1.234567e0)); + test(STR("12.3457"), en_US, STR("{:.6L}"), F(1.234567e1)); + test(STR("123.457"), en_US, STR("{:.6L}"), F(1.234567e2)); + test(STR("1,234.57"), en_US, STR("{:.6L}"), F(1.234567e3)); + test(STR("12,345.7"), en_US, STR("{:.6L}"), F(1.234567e4)); + test(STR("123,457"), en_US, STR("{:.6L}"), F(1.234567e5)); + test(STR("1.23457e+06"), en_US, STR("{:.6L}"), F(1.234567e6)); + test(STR("1.23457e+07"), en_US, STR("{:.6L}"), F(1.234567e7)); + test(STR("-1.23457e-06"), en_US, STR("{:.6L}"), F(-1.234567e-6)); + test(STR("-1.23457e-05"), en_US, STR("{:.6L}"), F(-1.234567e-5)); + test(STR("-0.000123457"), en_US, STR("{:.6L}"), F(-1.234567e-4)); + test(STR("-0.00123457"), en_US, STR("{:.6L}"), F(-1.234567e-3)); + test(STR("-0.0123457"), en_US, STR("{:.6L}"), F(-1.234567e-2)); + test(STR("-0.123457"), en_US, STR("{:.6L}"), F(-1.234567e-1)); + test(STR("-1.23457"), en_US, STR("{:.6L}"), F(-1.234567e0)); + test(STR("-12.3457"), en_US, STR("{:.6L}"), F(-1.234567e1)); + test(STR("-123.457"), en_US, STR("{:.6L}"), F(-1.234567e2)); + test(STR("-1,234.57"), en_US, STR("{:.6L}"), F(-1.234567e3)); + test(STR("-12,345.7"), en_US, STR("{:.6L}"), F(-1.234567e4)); + test(STR("-123,457"), en_US, STR("{:.6L}"), F(-1.234567e5)); + test(STR("-1.23457e+06"), en_US, STR("{:.6L}"), F(-1.234567e6)); + test(STR("-1.23457e+07"), en_US, STR("{:.6L}"), F(-1.234567e7)); + + std::locale::global(en_US); + test(STR("1#23457e-06"), loc, STR("{:.6L}"), F(1.234567e-6)); + test(STR("1#23457e-05"), loc, STR("{:.6L}"), F(1.234567e-5)); + test(STR("0#000123457"), loc, STR("{:.6L}"), F(1.234567e-4)); + test(STR("0#00123457"), loc, STR("{:.6L}"), F(1.234567e-3)); + test(STR("0#0123457"), loc, STR("{:.6L}"), F(1.234567e-2)); + test(STR("0#123457"), loc, STR("{:.6L}"), F(1.234567e-1)); + test(STR("1#23457"), loc, STR("{:.6L}"), F(1.234567e0)); + test(STR("1_2#3457"), loc, STR("{:.6L}"), F(1.234567e1)); + test(STR("12_3#457"), loc, STR("{:.6L}"), F(1.234567e2)); + test(STR("1_23_4#57"), loc, STR("{:.6L}"), F(1.234567e3)); + test(STR("12_34_5#7"), loc, STR("{:.6L}"), F(1.234567e4)); + test(STR("123_45_7"), loc, STR("{:.6L}"), F(1.234567e5)); + test(STR("1#23457e+06"), loc, STR("{:.6L}"), F(1.234567e6)); + test(STR("1#23457e+07"), loc, STR("{:.6L}"), F(1.234567e7)); + test(STR("-1#23457e-06"), loc, STR("{:.6L}"), F(-1.234567e-6)); + test(STR("-1#23457e-05"), loc, STR("{:.6L}"), F(-1.234567e-5)); + test(STR("-0#000123457"), loc, STR("{:.6L}"), F(-1.234567e-4)); + test(STR("-0#00123457"), loc, STR("{:.6L}"), F(-1.234567e-3)); + test(STR("-0#0123457"), loc, STR("{:.6L}"), F(-1.234567e-2)); + test(STR("-0#123457"), loc, STR("{:.6L}"), F(-1.234567e-1)); + test(STR("-1#23457"), loc, STR("{:.6L}"), F(-1.234567e0)); + test(STR("-1_2#3457"), loc, STR("{:.6L}"), F(-1.234567e1)); + test(STR("-12_3#457"), loc, STR("{:.6L}"), F(-1.234567e2)); + test(STR("-1_23_4#57"), loc, STR("{:.6L}"), F(-1.234567e3)); + test(STR("-12_34_5#7"), loc, STR("{:.6L}"), F(-1.234567e4)); + test(STR("-123_45_7"), loc, STR("{:.6L}"), F(-1.234567e5)); + test(STR("-1#23457e+06"), loc, STR("{:.6L}"), F(-1.234567e6)); + test(STR("-1#23457e+07"), loc, STR("{:.6L}"), F(-1.234567e7)); + + // *** Fill, align, zero padding *** + std::locale::global(en_US); + test(STR("1,234.57$$$"), STR("{:$<11.6L}"), F(1.234567e3)); + test(STR("$$$1,234.57"), STR("{:$>11.6L}"), F(1.234567e3)); + test(STR("$1,234.57$$"), STR("{:$^11.6L}"), F(1.234567e3)); + test(STR("0001,234.57"), STR("{:011.6L}"), F(1.234567e3)); + test(STR("-1,234.57$$$"), STR("{:$<12.6L}"), F(-1.234567e3)); + test(STR("$$$-1,234.57"), STR("{:$>12.6L}"), F(-1.234567e3)); + test(STR("$-1,234.57$$"), STR("{:$^12.6L}"), F(-1.234567e3)); + test(STR("-0001,234.57"), STR("{:012.6L}"), F(-1.234567e3)); + + std::locale::global(loc); + test(STR("1_23_4#57$$$"), STR("{:$<12.6L}"), F(1.234567e3)); + test(STR("$$$1_23_4#57"), STR("{:$>12.6L}"), F(1.234567e3)); + test(STR("$1_23_4#57$$"), STR("{:$^12.6L}"), F(1.234567e3)); + test(STR("0001_23_4#57"), STR("{:012.6L}"), F(1.234567e3)); + test(STR("-1_23_4#57$$$"), STR("{:$<13.6L}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#57"), STR("{:$>13.6L}"), F(-1.234567e3)); + test(STR("$-1_23_4#57$$"), STR("{:$^13.6L}"), F(-1.234567e3)); + test(STR("-0001_23_4#57"), STR("{:013.6L}"), F(-1.234567e3)); + + test(STR("1,234.57$$$"), en_US, STR("{:$<11.6L}"), F(1.234567e3)); + test(STR("$$$1,234.57"), en_US, STR("{:$>11.6L}"), F(1.234567e3)); + test(STR("$1,234.57$$"), en_US, STR("{:$^11.6L}"), F(1.234567e3)); + test(STR("0001,234.57"), en_US, STR("{:011.6L}"), F(1.234567e3)); + test(STR("-1,234.57$$$"), en_US, STR("{:$<12.6L}"), F(-1.234567e3)); + test(STR("$$$-1,234.57"), en_US, STR("{:$>12.6L}"), F(-1.234567e3)); + test(STR("$-1,234.57$$"), en_US, STR("{:$^12.6L}"), F(-1.234567e3)); + test(STR("-0001,234.57"), en_US, STR("{:012.6L}"), F(-1.234567e3)); + + std::locale::global(en_US); + test(STR("1_23_4#57$$$"), loc, STR("{:$<12.6L}"), F(1.234567e3)); + test(STR("$$$1_23_4#57"), loc, STR("{:$>12.6L}"), F(1.234567e3)); + test(STR("$1_23_4#57$$"), loc, STR("{:$^12.6L}"), F(1.234567e3)); + test(STR("0001_23_4#57"), loc, STR("{:012.6L}"), F(1.234567e3)); + test(STR("-1_23_4#57$$$"), loc, STR("{:$<13.6L}"), F(-1.234567e3)); + test(STR("$$$-1_23_4#57"), loc, STR("{:$>13.6L}"), F(-1.234567e3)); + test(STR("$-1_23_4#57$$"), loc, STR("{:$^13.6L}"), F(-1.234567e3)); + test(STR("-0001_23_4#57"), loc, STR("{:013.6L}"), F(-1.234567e3)); +} + +template +void test_floating_point() { + + test_floating_point_hex_lower_case(); + test_floating_point_hex_upper_case(); + test_floating_point_hex_lower_case_precision(); + test_floating_point_hex_upper_case_precision(); + + test_floating_point_scientific_lower_case(); + test_floating_point_scientific_upper_case(); + + test_floating_point_fixed_lower_case(); + test_floating_point_fixed_upper_case(); + + test_floating_point_general_lower_case(); + test_floating_point_general_upper_case(); + + test_floating_point_default(); + test_floating_point_default_precision(); +} + template void test() { test_bool(); test_integer(); + test_floating_point(); + test_floating_point(); + test_floating_point(); } int main(int, char**) {