[libcxx-commits] [libcxx] db2944e - [libc++][format] Adds formatter floating-point.
Mark de Wever via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Jan 24 09:12:35 PST 2022
Author: Mark de Wever
Date: 2022-01-24T18:12:24+01:00
New Revision: db2944e34b16387bf4326ddfd2a8c420594572f4
URL: https://github.com/llvm/llvm-project/commit/db2944e34b16387bf4326ddfd2a8c420594572f4
DIFF: https://github.com/llvm/llvm-project/commit/db2944e34b16387bf4326ddfd2a8c420594572f4.diff
LOG: [libc++][format] Adds formatter floating-point.
This properly implements the formatter for floating-point types.
Completes:
- P1652R1 Printf corner cases in std::format
- LWG 3250 std::format: # (alternate form) for NaN and inf
- LWG 3243 std::format and negative zeroes
Implements parts of:
- P0645 Text Formatting
Reviewed By: #libc, ldionne, vitaut
Differential Revision: https://reviews.llvm.org/D114001
Added:
libcxx/benchmarks/formatter_float.bench.cpp
libcxx/include/__format/formatter_floating_point.h
libcxx/test/libcxx/diagnostics/detail.headers/format/formatter_floating_point.module.verify.cpp
libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_floating_point.pass.cpp
Modified:
libcxx/docs/Status/Cxx20Issues.csv
libcxx/docs/Status/Cxx20Papers.csv
libcxx/include/CMakeLists.txt
libcxx/include/__format/formatter.h
libcxx/include/__format/formatter_integral.h
libcxx/include/__format/parser_std_format_spec.h
libcxx/include/format
libcxx/include/module.modulemap
libcxx/test/std/utilities/format/format.formatter/format.context/format.formatter.spec/formatter.floating_point.pass.cpp
libcxx/test/std/utilities/format/format.functions/format_tests.h
libcxx/test/std/utilities/format/format.functions/locale-specific_form.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/benchmarks/formatter_float.bench.cpp b/libcxx/benchmarks/formatter_float.bench.cpp
new file mode 100644
index 0000000000000..3190b3779c5d9
--- /dev/null
+++ b/libcxx/benchmarks/formatter_float.bench.cpp
@@ -0,0 +1,241 @@
+//===----------------------------------------------------------------------===//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <format>
+
+#include <array>
+#include <limits>
+#include <random>
+#include <string>
+
+#include "CartesianBenchmarks.h"
+#include "benchmark/benchmark.h"
+
+// *** Localization ***
+enum class LocalizationE { False, True };
+struct AllLocalizations : EnumValuesAsTuple<AllLocalizations, LocalizationE, 2> {
+ static constexpr const char* Names[] = {"LocFalse", "LocTrue"};
+};
+
+template <LocalizationE E>
+struct Localization {};
+
+template <>
+struct Localization<LocalizationE::False> {
+ static constexpr const char* fmt = "";
+};
+
+template <>
+struct Localization<LocalizationE::True> {
+ static constexpr const char* fmt = "L";
+};
+
+// *** Types ***
+enum class TypeE { Float, Double, LongDouble };
+// TODO FMT Set to 3 after to_chars has long double suport.
+struct AllTypes : EnumValuesAsTuple<AllTypes, TypeE, 2> {
+ static constexpr const char* Names[] = {"Float", "Double", "LongDouble"};
+};
+
+template <TypeE E>
+struct Type {};
+
+template <>
+struct Type<TypeE::Float> {
+ using type = float;
+};
+
+template <>
+struct Type<TypeE::Double> {
+ using type = double;
+};
+
+template <>
+struct Type<TypeE::LongDouble> {
+ using type = long double;
+};
+
+// *** Values ***
+enum class ValueE { Inf, Random };
+struct AllValues : EnumValuesAsTuple<AllValues, ValueE, 2> {
+ static constexpr const char* Names[] = {"Inf", "Random"};
+};
+
+template <ValueE E>
+struct Value {};
+
+template <>
+struct Value<ValueE::Inf> {
+ template <class F>
+ static std::array<F, 1000> make_data() {
+ std::array<F, 1000> result;
+ std::fill(result.begin(), result.end(), -std::numeric_limits<F>::infinity());
+ return result;
+ }
+};
+
+template <>
+struct Value<ValueE::Random> {
+ template <class F>
+ static std::array<F, 1000> make_data() {
+ std::random_device seed;
+ std::mt19937 generator(seed());
+ std::uniform_int_distribution<std::conditional_t<sizeof(F) == sizeof(uint32_t), uint32_t, uint64_t>> distribution;
+
+ std::array<F, 1000> result;
+ std::generate(result.begin(), result.end(), [&] {
+ while (true) {
+ auto result = std::bit_cast<F>(distribution(generator));
+ if (std::isfinite(result))
+ return result;
+ }
+ });
+ return result;
+ }
+};
+
+// *** Display Type ***
+enum class DisplayTypeE {
+ Default,
+ Hex,
+ Scientific,
+ Fixed,
+ General,
+};
+struct AllDisplayTypes : EnumValuesAsTuple<AllDisplayTypes, DisplayTypeE, 5> {
+ static constexpr const char* Names[] = {"DisplayDefault", "DisplayHex", "DisplayScientific", "DisplayFixed",
+ "DisplayGeneral"};
+};
+
+template <DisplayTypeE E>
+struct DisplayType {};
+
+template <>
+struct DisplayType<DisplayTypeE::Default> {
+ static constexpr const char* fmt = "";
+};
+
+template <>
+struct DisplayType<DisplayTypeE::Hex> {
+ static constexpr const char* fmt = "a";
+};
+
+template <>
+struct DisplayType<DisplayTypeE::Scientific> {
+ static constexpr const char* fmt = "e";
+};
+
+template <>
+struct DisplayType<DisplayTypeE::Fixed> {
+ static constexpr const char* fmt = "f";
+};
+
+template <>
+struct DisplayType<DisplayTypeE::General> {
+ static constexpr const char* fmt = "g";
+};
+
+// *** Alignment ***
+enum class AlignmentE { None, Left, Center, Right, ZeroPadding };
+struct AllAlignments : EnumValuesAsTuple<AllAlignments, AlignmentE, 5> {
+ static constexpr const char* Names[] = {"AlignNone", "AlignmentLeft", "AlignmentCenter", "AlignmentRight",
+ "ZeroPadding"};
+};
+
+template <AlignmentE E>
+struct Alignment {};
+
+template <>
+struct Alignment<AlignmentE::None> {
+ static constexpr const char* fmt = "";
+};
+
+template <>
+struct Alignment<AlignmentE::Left> {
+ // Width > PrecisionE::Huge
+ static constexpr const char* fmt = "0<17500";
+};
+
+template <>
+struct Alignment<AlignmentE::Center> {
+ // Width > PrecisionE::Huge
+ static constexpr const char* fmt = "0^17500";
+};
+
+template <>
+struct Alignment<AlignmentE::Right> {
+ // Width > PrecisionE::Huge
+ static constexpr const char* fmt = "0>17500";
+};
+
+template <>
+struct Alignment<AlignmentE::ZeroPadding> {
+ // Width > PrecisionE::Huge
+ static constexpr const char* fmt = "017500";
+};
+
+enum class PrecisionE { None, Zero, Small, Huge };
+struct AllPrecisions : EnumValuesAsTuple<AllPrecisions, PrecisionE, 4> {
+ static constexpr const char* Names[] = {"PrecNone", "PrecZero", "PrecSmall", "PrecHuge"};
+};
+
+template <PrecisionE E>
+struct Precision {};
+
+template <>
+struct Precision<PrecisionE::None> {
+ static constexpr const char* fmt = "";
+};
+
+template <>
+struct Precision<PrecisionE::Zero> {
+ static constexpr const char* fmt = ".0";
+};
+
+template <>
+struct Precision<PrecisionE::Small> {
+ static constexpr const char* fmt = ".10";
+};
+
+template <>
+struct Precision<PrecisionE::Huge> {
+ // The maximum precision for a minimal sub normal long double is ±0x1p-16494.
+ // This value is always larger than that value forcing the trailing zero path
+ // to be executed.
+ static constexpr const char* fmt = ".17000";
+};
+
+template <class L, class DT, class T, class V, class A, class P>
+struct FloatingPoint {
+ using F = typename Type<T::value>::type;
+
+ void run(benchmark::State& state) const {
+ std::array<F, 1000> data{Value<V::value>::template make_data<F>()};
+ std::array<char, 20'000> output;
+ std::string fmt{std::string("{:") + Alignment<A::value>::fmt + Precision<P::value>::fmt +
+ Localization<L::value>::fmt + DisplayType<DT::value>::fmt + "}"};
+
+ while (state.KeepRunningBatch(1000))
+ for (F value : data)
+ benchmark::DoNotOptimize(std::format_to(output.begin(), fmt, value));
+ }
+
+ std::string name() const {
+ return "FloatingPoint" + L::name() + DT::name() + T::name() + V::name() + A::name() + P::name();
+ }
+};
+
+int main(int argc, char** argv) {
+ benchmark::Initialize(&argc, argv);
+ if (benchmark::ReportUnrecognizedArguments(argc, argv))
+ return 1;
+
+ makeCartesianProductBenchmark<FloatingPoint, AllLocalizations, AllDisplayTypes, AllTypes, AllValues, AllAlignments,
+ AllPrecisions>();
+
+ benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv
index f93e66fda1849..034fac3ca22f8 100644
--- a/libcxx/docs/Status/Cxx20Issues.csv
+++ b/libcxx/docs/Status/Cxx20Issues.csv
@@ -203,10 +203,10 @@
"`3237 <https://wg21.link/LWG3237>`__","LWG 3038 and 3190 have inconsistent PRs","Prague","|Complete|","14.0"
"`3238 <https://wg21.link/LWG3238>`__","Insufficiently-defined behavior of ``std::function``\ deduction guides","Prague","",""
"`3242 <https://wg21.link/LWG3242>`__","``std::format``\ : missing rules for ``arg-id``\ in ``width``\ and ``precision``\ ","Prague","|Complete|","Clang 14","|format|"
-"`3243 <https://wg21.link/LWG3243>`__","``std::format``\ and negative zeroes","Prague","","","|format|"
+"`3243 <https://wg21.link/LWG3243>`__","``std::format``\ and negative zeroes","Prague","|Complete|","14.0","|format|"
"`3247 <https://wg21.link/LWG3247>`__","``ranges::iter_move``\ should perform ADL-only lookup of ``iter_move``\ ","Prague","","","|ranges|"
"`3248 <https://wg21.link/LWG3248>`__","``std::format``\ ``#b``\ , ``#B``\ , ``#o``\ , ``#x``\ , and ``#X``\ presentation types misformat negative numbers","Prague","|Complete|","14.0","|format|"
-"`3250 <https://wg21.link/LWG3250>`__","``std::format``\ : ``#``\ (alternate form) for NaN and inf","Prague","","","|format|"
+"`3250 <https://wg21.link/LWG3250>`__","``std::format``\ : ``#``\ (alternate form) for NaN and inf","Prague","|Complete|","14.0","|format|"
"`3251 <https://wg21.link/LWG3251>`__","Are ``std::format``\ alignment specifiers applied to string arguments?","Prague","","","|format|"
"`3252 <https://wg21.link/LWG3252>`__","Parse locale's aware modifiers for commands are not consistent with POSIX spec","Prague","","","|chrono|"
"`3254 <https://wg21.link/LWG3254>`__","Strike ``stop_token``\ 's ``operator!=``\ ","Prague","",""
diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
index d0927e09426ce..5a974a798f7bd 100644
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -129,7 +129,7 @@
"`P1644R0 <https://wg21.link/P1644R0>`__","LWG","Add wait/notify to atomic<shared_ptr>","Cologne","",""
"`P1650R0 <https://wg21.link/P1650R0>`__","LWG","Output std::chrono::days with 'd' suffix","Cologne","",""
"`P1651R0 <https://wg21.link/P1651R0>`__","LWG","bind_front should not unwrap reference_wrapper","Cologne","|Complete|","13.0"
-"`P1652R1 <https://wg21.link/P1652R1>`__","LWG","Printf corner cases in std::format","Cologne","|In Progress|",""
+"`P1652R1 <https://wg21.link/P1652R1>`__","LWG","Printf corner cases in std::format","Cologne","|Complete|","14.0"
"`P1661R1 <https://wg21.link/P1661R1>`__","LWG","Remove dedicated precalculated hash lookup interface","Cologne","|Nothing To Do|",""
"`P1754R1 <https://wg21.link/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
index b7222540846fa..3886ddba8e4e5 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -178,6 +178,7 @@ set(files
__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
index 1adce75a86110..0c0c02ba19173 100644
--- a/libcxx/include/__format/formatter.h
+++ b/libcxx/include/__format/formatter.h
@@ -190,6 +190,34 @@ __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
}
+/**
+ * @overload
+ *
+ * Writes additional zero's for the precision before the exponent.
+ * This is used when the precision requested in the format string is larger
+ * than the maximum precision of the floating-point type. These precision
+ * digits are always 0.
+ *
+ * @param __exponent The location of the exponent character.
+ * @param __num_trailing_zeros The number of 0's to write before the exponent
+ * character.
+ */
+template <class _CharT, class _Fill>
+_LIBCPP_HIDE_FROM_ABI auto __write(output_iterator<const _CharT&> auto __out_it, const _CharT* __first,
+ const _CharT* __last, size_t __size, size_t __width, _Fill __fill,
+ __format_spec::_Flags::_Alignment __alignment, const _CharT* __exponent,
+ size_t __num_trailing_zeros) -> decltype(__out_it) {
+ _LIBCPP_ASSERT(__first <= __last, "Not a valid range");
+ _LIBCPP_ASSERT(__num_trailing_zeros > 0, "The overload not writing trailing zeros should have been used");
+
+ __padding_size_result __padding = __padding_size(__size + __num_trailing_zeros, __width, __alignment);
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
+ __out_it = _VSTD::copy(__first, __exponent, _VSTD::move(__out_it));
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __num_trailing_zeros, _CharT('0'));
+ __out_it = _VSTD::copy(__exponent, __last, _VSTD::move(__out_it));
+ return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
+}
+
/**
* @overload
*
diff --git a/libcxx/include/__format/formatter_floating_point.h b/libcxx/include/__format/formatter_floating_point.h
new file mode 100644
index 0000000000000..2e710b409deb6
--- /dev/null
+++ b/libcxx/include/__format/formatter_floating_point.h
@@ -0,0 +1,717 @@
+// -*- 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/fill_n.h>
+#include <__algorithm/find.h>
+#include <__algorithm/min.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 <__format/formatter_integral.h>
+#include <__format/parser_std_format_spec.h>
+#include <__utility/move.h>
+#include <charconv>
+#include <cmath>
+
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+# include <locale>
+#endif
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_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 {
+
+template <floating_point _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value) {
+ to_chars_result __r = _VSTD::to_chars(__first, __last, __value);
+ _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+ return __r.ptr;
+}
+
+template <floating_point _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt) {
+ to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt);
+ _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+ return __r.ptr;
+}
+
+template <floating_point _Tp>
+_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, chars_format __fmt, int __precision) {
+ to_chars_result __r = _VSTD::to_chars(__first, __last, __value, __fmt, __precision);
+ _LIBCPP_ASSERT(__r.ec == errc(0), "Internal buffer too small");
+ return __r.ptr;
+}
+
+// https://en.cppreference.com/w/cpp/language/types#cite_note-1
+// float min subnormal: +/-0x1p-149 max: +/- 3.402,823,4 10^38
+// double min subnormal: +/-0x1p-1074 max +/- 1.797,693,134,862,315,7 10^308
+// long double (x86) min subnormal: +/-0x1p-16446 max: +/- 1.189,731,495,357,231,765,021 10^4932
+//
+// The maximum number of digits required for the integral part is based on the
+// maximum's value power of 10. Every power of 10 requires one additional
+// decimal digit.
+// The maximum number of digits required for the fractional part is based on
+// the minimal subnormal hexadecimal output's power of 10. Every division of a
+// fraction's binary 1 by 2, requires one additional decimal digit.
+//
+// The maximum size of a formatted value depends on the selected output format.
+// Ignoring the fact the format string can request a precision larger than the
+// values maximum required, these values are:
+//
+// sign 1 code unit
+// __max_integral
+// radix point 1 code unit
+// __max_fractional
+// exponent character 1 code unit
+// sign 1 code unit
+// __max_fractional_value
+// -----------------------------------
+// total 4 code units extra required.
+//
+// TODO FMT Optimize the storage to avoid storing digits that are known to be zero.
+// https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
+
+// TODO FMT Add long double specialization when to_chars has proper long double support.
+template <class _Tp>
+struct __traits;
+
+template <floating_point _Fp>
+static constexpr size_t __float_buffer_size(int __precision) {
+ using _Traits = __traits<_Fp>;
+ return 4 + _Traits::__max_integral + __precision + _Traits::__max_fractional_value;
+}
+
+template <>
+struct __traits<float> {
+ static constexpr int __max_integral = 38;
+ static constexpr int __max_fractional = 149;
+ static constexpr int __max_fractional_value = 3;
+ static constexpr size_t __stack_buffer_size = 256;
+
+ static constexpr int __hex_precision_digits = 3;
+};
+
+template <>
+struct __traits<double> {
+ static constexpr int __max_integral = 308;
+ static constexpr int __max_fractional = 1074;
+ static constexpr int __max_fractional_value = 4;
+ static constexpr size_t __stack_buffer_size = 1024;
+
+ static constexpr int __hex_precision_digits = 4;
+};
+
+/// Helper class to store the conversion buffer.
+///
+/// Depending on the maxium size required for a value, the buffer is allocated
+/// on the stack or the heap.
+template <floating_point _Fp>
+class _LIBCPP_TEMPLATE_VIS __float_buffer {
+ using _Traits = __traits<_Fp>;
+
+public:
+ // TODO FMT Improve this constructor to do a better estimate.
+ // When using a scientific formatting with a precision of 6 a stack buffer
+ // will always suffice. At the moment that isn't important since floats and
+ // doubles use a stack buffer, unless the precision used in the format string
+ // is large.
+ // When supporting long doubles the __max_integral part becomes 4932 which
+ // may be too much for some platforms. For these cases a better estimate is
+ // required.
+ explicit _LIBCPP_HIDE_FROM_ABI __float_buffer(int __precision)
+ : __precision_(__precision != -1 ? __precision : _Traits::__max_fractional) {
+
+ // When the precision is larger than _Traits::__max_fractional the digits in
+ // the range (_Traits::__max_fractional, precision] will contain the value
+ // zero. There's no need to request to_chars to write these zeros:
+ // - When the value is large a temporary heap buffer needs to be allocated.
+ // - When to_chars writes the values they need to be "copied" to the output:
+ // - char: std::fill on the output iterator is faster than std::copy.
+ // - wchar_t: same argument as char, but additional std::copy won't work.
+ // The input is always a char buffer, so every char in the buffer needs
+ // to be converted from a char to a wchar_t.
+ if (__precision_ > _Traits::__max_fractional) {
+ __num_trailing_zeros_ = __precision_ - _Traits::__max_fractional;
+ __precision_ = _Traits::__max_fractional;
+ }
+
+ __size_ = __format_spec::__float_buffer_size<_Fp>(__precision_);
+ if (__size_ > _Traits::__stack_buffer_size)
+ // The allocated buffer's contents don't need initialization.
+ __begin_ = allocator<char>{}.allocate(__size_);
+ else
+ __begin_ = __buffer_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI ~__float_buffer() {
+ if (__size_ > _Traits::__stack_buffer_size)
+ allocator<char>{}.deallocate(__begin_, __size_);
+ }
+ _LIBCPP_HIDE_FROM_ABI __float_buffer(const __float_buffer&) = delete;
+ _LIBCPP_HIDE_FROM_ABI __float_buffer& operator=(const __float_buffer&) = delete;
+
+ _LIBCPP_HIDE_FROM_ABI char* begin() const { return __begin_; }
+ _LIBCPP_HIDE_FROM_ABI char* end() const { return __begin_ + __size_; }
+
+ _LIBCPP_HIDE_FROM_ABI int __precision() const { return __precision_; }
+ _LIBCPP_HIDE_FROM_ABI int __num_trailing_zeros() const { return __num_trailing_zeros_; }
+ _LIBCPP_HIDE_FROM_ABI void __remove_trailing_zeros() { __num_trailing_zeros_ = 0; }
+
+private:
+ int __precision_;
+ int __num_trailing_zeros_{0};
+ size_t __size_;
+ char* __begin_;
+ char __buffer_[_Traits::__stack_buffer_size];
+};
+
+struct __float_result {
+ /// Points at the beginning of the integral part in the buffer.
+ ///
+ /// When there's no sign character this points at the start of the buffer.
+ char* __integral;
+
+ /// Points at the radix point, when not present it's the same as \ref __last.
+ char* __radix_point;
+
+ /// Points at the exponent character, when not present it's the same as \ref __last.
+ char* __exponent;
+
+ /// Points beyond the last written element in the buffer.
+ char* __last;
+};
+
+/// Finds the position of the exponent character 'e' at the end of the buffer.
+///
+/// Assuming there is an exponent the input will terminate with
+/// eSdd and eSdddd (S = sign, d = digit)
+///
+/// \returns a pointer to the exponent or __last when not found.
+constexpr inline _LIBCPP_HIDE_FROM_ABI char* __find_exponent(char* __first, char* __last) {
+ ptr
diff _t __size = __last - __first;
+ if (__size > 4) {
+ __first = __last - _VSTD::min(__size, ptr
diff _t(6));
+ for (; __first != __last - 3; ++__first) {
+ if (*__first == 'e')
+ return __first;
+ }
+ }
+ return __last;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_default(const __float_buffer<_Fp>& __buffer, _Tp __value,
+ char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value);
+
+ __result.__exponent = __format_spec::__find_exponent(__result.__integral, __result.__last);
+
+ // Constrains:
+ // - There's at least one decimal digit before the radix point.
+ // - The radix point, when present, is placed before the exponent.
+ __result.__radix_point = _VSTD::find(__result.__integral + 1, __result.__exponent, '.');
+
+ // When the radix point isn't found its position is the exponent instead of
+ // __result.__last.
+ if (__result.__radix_point == __result.__exponent)
+ __result.__radix_point = __result.__last;
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent == __result.__last || *__result.__exponent == 'e'),
+ "Post-condition failure.");
+ // clang-format on
+
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_lower_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ if (__precision == -1)
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex);
+ else
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::hex, __precision);
+
+ // H = one or more hex-digits
+ // S = sign
+ // D = one or more decimal-digits
+ // When the fractional part is zero and no precision the output is 0p+0
+ // else the output is 0.HpSD
+ // So testing the second position can
diff erentiate between these two cases.
+ char* __first = __integral + 1;
+ if (*__first == '.') {
+ __result.__radix_point = __first;
+ // One digit is the minimum
+ // 0.hpSd
+ // ^-- last
+ // ^---- integral = end of search
+ // ^-------- start of search
+ // 0123456
+ //
+ // Four digits is the maximum
+ // 0.hpSdddd
+ // ^-- last
+ // ^---- integral = end of search
+ // ^-------- start of search
+ // 0123456789
+ static_assert(__traits<_Fp>::__hex_precision_digits <= 4, "Guard against possible underflow.");
+
+ char* __last = __result.__last - 2;
+ __first = __last - __traits<_Fp>::__hex_precision_digits;
+ __result.__exponent = _VSTD::find(__first, __last, 'p');
+ } else {
+ __result.__radix_point = __result.__last;
+ __result.__exponent = __first;
+ }
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent != __result.__last && *__result.__exponent == 'p'),
+ "Post-condition failure.");
+ // clang-format on
+
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_hexadecimal_upper_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result =
+ __format_spec::__format_buffer_hexadecimal_lower_case(__buffer, __value, __precision, __integral);
+ _VSTD::transform(__result.__integral, __result.__exponent, __result.__integral, __hex_to_upper);
+ *__result.__exponent = 'P';
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_lower_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last =
+ __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::scientific, __precision);
+
+ char* __first = __integral + 1;
+ _LIBCPP_ASSERT(__first != __result.__last, "No exponent present");
+ if (*__first == '.') {
+ __result.__radix_point = __first;
+ __result.__exponent = __format_spec::__find_exponent(__first + 1, __result.__last);
+ } else {
+ __result.__radix_point = __result.__last;
+ __result.__exponent = __first;
+ }
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent != __result.__last && *__result.__exponent == 'e'),
+ "Post-condition failure.");
+ // clang-format on
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_scientific_upper_case(const __float_buffer<_Fp>& __buffer,
+ _Tp __value, int __precision,
+ char* __integral) {
+ __float_result __result =
+ __format_spec::__format_buffer_scientific_lower_case(__buffer, __value, __precision, __integral);
+ *__result.__exponent = 'E';
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_fixed(const __float_buffer<_Fp>& __buffer, _Tp __value,
+ int __precision, char* __integral) {
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::fixed, __precision);
+
+ // When there's no precision there's no radix point.
+ // Else the radix point is placed at __precision + 1 from the end.
+ // By converting __precision to a bool the subtraction can be done
+ // unconditionally.
+ __result.__radix_point = __result.__last - (__precision + bool(__precision));
+ __result.__exponent = __result.__last;
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent == __result.__last),
+ "Post-condition failure.");
+ // clang-format on
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_lower_case(__float_buffer<_Fp>& __buffer, _Tp __value,
+ int __precision, char* __integral) {
+
+ __buffer.__remove_trailing_zeros();
+
+ __float_result __result;
+ __result.__integral = __integral;
+ __result.__last = __format_spec::__to_buffer(__integral, __buffer.end(), __value, chars_format::general, __precision);
+
+ char* __first = __integral + 1;
+ if (__first == __result.__last) {
+ __result.__radix_point = __result.__last;
+ __result.__exponent = __result.__last;
+ } else {
+ __result.__exponent = __format_spec::__find_exponent(__first, __result.__last);
+ if (__result.__exponent != __result.__last)
+ // In scientific mode if there's a radix point it will always be after
+ // the first digit. (This is the position __first points at).
+ __result.__radix_point = *__first == '.' ? __first : __result.__last;
+ else {
+ // In fixed mode the algorithm truncates trailing spaces and possibly the
+ // radix point. There's no good guess for the position of the radix point
+ // therefore scan the output after the first digit.
+ __result.__radix_point = _VSTD::find(__first, __result.__last, '.');
+ }
+ }
+
+ // clang-format off
+ _LIBCPP_ASSERT((__result.__integral != __result.__last) &&
+ (__result.__radix_point == __result.__last || *__result.__radix_point == '.') &&
+ (__result.__exponent == __result.__last || *__result.__exponent == 'e'),
+ "Post-condition failure.");
+ // clang-format on
+
+ return __result;
+}
+
+template <class _Fp, class _Tp>
+_LIBCPP_HIDE_FROM_ABI __float_result __format_buffer_general_upper_case(__float_buffer<_Fp>& __buffer, _Tp __value,
+ int __precision, char* __integral) {
+ __float_result __result =
+ __format_spec::__format_buffer_general_lower_case(__buffer, __value, __precision, __integral);
+ if (__result.__exponent != __result.__last)
+ *__result.__exponent = 'E';
+ return __result;
+}
+
+# ifndef _LIBCPP_HAS_NO_LOCALIZATION
+template <class _OutIt, class _Fp, class _CharT>
+_LIBCPP_HIDE_FROM_ABI _OutIt __format_locale_specific_form(_OutIt __out_it, const __float_buffer<_Fp>& __buffer,
+ const __float_result& __result, _VSTD::locale __loc,
+ size_t __width, _Flags::_Alignment __alignment,
+ _CharT __fill) {
+ const auto& __np = use_facet<numpunct<_CharT>>(__loc);
+ string __grouping = __np.grouping();
+ char* __first = __result.__integral;
+ // When no radix point or exponent are present __last will be __result.__last.
+ char* __last = _VSTD::min(__result.__radix_point, __result.__exponent);
+
+ ptr
diff _t __digits = __last - __first;
+ if (!__grouping.empty()) {
+ if (__digits <= __grouping[0])
+ __grouping.clear();
+ else
+ __grouping = __determine_grouping(__digits, __grouping);
+ }
+
+ size_t __size = __result.__last - __buffer.begin() + // Formatted string
+ __buffer.__num_trailing_zeros() + // Not yet rendered zeros
+ __grouping.size() - // Grouping contains one
+ !__grouping.empty(); // additional character
+
+ __formatter::__padding_size_result __padding = {0, 0};
+ bool __zero_padding = __alignment == _Flags::_Alignment::__default;
+ if (__size < __width) {
+ if (__zero_padding) {
+ __alignment = _Flags::_Alignment::__right;
+ __fill = _CharT('0');
+ }
+
+ __padding = __formatter::__padding_size(__size, __width, __alignment);
+ }
+
+ // sign and (zero padding or alignment)
+ if (__zero_padding && __first != __buffer.begin())
+ *__out_it++ = *__buffer.begin();
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __padding.__before, __fill);
+ if (!__zero_padding && __first != __buffer.begin())
+ *__out_it++ = *__buffer.begin();
+
+ // integral part
+ if (__grouping.empty()) {
+ __out_it = _VSTD::copy_n(__first, __digits, _VSTD::move(__out_it));
+ } else {
+ auto __r = __grouping.rbegin();
+ auto __e = __grouping.rend() - 1;
+ _CharT __sep = __np.thousands_sep();
+ // 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.
+ while (true) {
+ __out_it = _VSTD::copy_n(__first, *__r, _VSTD::move(__out_it));
+ __first += *__r;
+
+ if (__r == __e)
+ break;
+
+ ++__r;
+ *__out_it++ = __sep;
+ }
+ }
+
+ // fractional part
+ if (__result.__radix_point != __result.__last) {
+ *__out_it++ = __np.decimal_point();
+ __out_it = _VSTD::copy(__result.__radix_point + 1, __result.__exponent, _VSTD::move(__out_it));
+ __out_it = _VSTD::fill_n(_VSTD::move(__out_it), __buffer.__num_trailing_zeros(), _CharT('0'));
+ }
+
+ // exponent
+ if (__result.__exponent != __result.__last)
+ __out_it = _VSTD::copy(__result.__exponent, __result.__last, _VSTD::move(__out_it));
+
+ // alignment
+ return _VSTD::fill_n(_VSTD::move(__out_it), __padding.__after, __fill);
+}
+
+# endif // _LIBCPP_HAS_NO_LOCALIZATION
+
+template <__formatter::__char_type _CharT>
+class _LIBCPP_TEMPLATE_VIS __formatter_floating_point : public __parser_floating_point<_CharT> {
+public:
+ template <floating_point _Tp>
+ _LIBCPP_HIDE_FROM_ABI auto format(_Tp __value, auto& __ctx) -> decltype(__ctx.out()) {
+ if (this->__width_needs_substitution())
+ this->__substitute_width_arg_id(__ctx.arg(this->__width));
+
+ bool __negative = _VSTD::signbit(__value);
+
+ if (!_VSTD::isfinite(__value)) [[unlikely]]
+ return __format_non_finite(__ctx.out(), __negative, _VSTD::isnan(__value));
+
+ bool __has_precision = this->__has_precision_field();
+ 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 non negative value.
+ // The function @ref __insert_sign will insert a '-' when the value was
+ // negative.
+
+ if (__negative)
+ __value = _VSTD::copysign(__value, +1.0);
+
+ // TODO FMT _Fp should just be _Tp when to_chars has proper long double support.
+ using _Fp = conditional_t<same_as<_Tp, long double>, double, _Tp>;
+ // Force the type of the precision to avoid -1 to become an unsigned value.
+ __float_buffer<_Fp> __buffer(__has_precision ? int(this->__precision) : -1);
+ __float_result __result = __format_buffer(__buffer, __value, __negative, __has_precision);
+
+ if (this->__alternate_form && __result.__radix_point == __result.__last) {
+ *__result.__last++ = '.';
+
+ // When there is an exponent the point needs to be moved before the
+ // exponent. When there's no exponent the rotate does nothing. Since
+ // rotate tests whether the operation is a nop, call it unconditionally.
+ _VSTD::rotate(__result.__exponent, __result.__last - 1, __result.__last);
+ __result.__radix_point = __result.__exponent;
+
+ // The radix point is always placed before the exponent.
+ // - No exponent needs to point to the new last.
+ // - An exponent needs to move one position to the right.
+ // So it's safe to increment the value unconditionally.
+ ++__result.__exponent;
+ }
+
+# ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ if (this->__locale_specific_form)
+ return __format_spec::__format_locale_specific_form(__ctx.out(), __buffer, __result, __ctx.locale(),
+ this->__width, this->__alignment, this->__fill);
+# endif
+
+ ptr
diff _t __size = __result.__last - __buffer.begin();
+ int __num_trailing_zeros = __buffer.__num_trailing_zeros();
+ if (__size + __num_trailing_zeros >= this->__width) {
+ if (__num_trailing_zeros && __result.__exponent != __result.__last)
+ // Insert trailing zeros before exponent character.
+ return _VSTD::copy(__result.__exponent, __result.__last,
+ _VSTD::fill_n(_VSTD::copy(__buffer.begin(), __result.__exponent, __ctx.out()),
+ __num_trailing_zeros, _CharT('0')));
+
+ return _VSTD::fill_n(_VSTD::copy(__buffer.begin(), __result.__last, __ctx.out()), __num_trailing_zeros,
+ _CharT('0'));
+ }
+
+ auto __out_it = __ctx.out();
+ char* __first = __buffer.begin();
+ if (this->__alignment == _Flags::_Alignment::__default) {
+ // When there 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 != __result.__integral)
+ *__out_it++ = *__first++;
+ // 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 (__num_trailing_zeros)
+ return __formatter::__write(_VSTD::move(__out_it), __first, __result.__last, __size, this->__width, this->__fill,
+ this->__alignment, __result.__exponent, __num_trailing_zeros);
+
+ return __formatter::__write(_VSTD::move(__out_it), __first, __result.__last, __size, this->__width, this->__fill,
+ this->__alignment);
+ }
+
+private:
+ template <class _OutIt>
+ _LIBCPP_HIDE_FROM_ABI _OutIt __format_non_finite(_OutIt __out_it, bool __negative, bool __isnan) {
+ char __buffer[4];
+ char* __last = __insert_sign(__buffer, __negative, this->__sign);
+
+ // 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 * __isnan]),
+ 3, __last);
+
+ // [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;
+
+ ptr
diff _t __size = __last - __buffer;
+ if (__size >= this->__width)
+ return _VSTD::copy_n(__buffer, __size, _VSTD::move(__out_it));
+
+ return __formatter::__write(_VSTD::move(__out_it), __buffer, __last, __size, this->__width, this->__fill,
+ this->__alignment);
+ }
+
+ /// Fills the buffer with the data based on the requested formatting.
+ ///
+ /// This function, when needed, turns the characters to upper case and
+ /// determines the "interesting" locations which are returned to the caller.
+ ///
+ /// This means the caller never has to convert the contents of the buffer to
+ /// upper case or search for radix points and the location of the exponent.
+ /// This gives a bit of overhead. The original code didn't do that, but due
+ /// to the number of possible additional work needed to turn this number to
+ /// the proper output the code was littered with tests for upper cases and
+ /// searches for radix points and exponents.
+ /// - When a precision larger than the type's precision is selected
+ /// additional zero characters need to be written before the exponent.
+ /// - alternate form needs to add a radix point when not present.
+ /// - localization needs to do grouping in the integral part.
+ template <class _Fp, class _Tp>
+ // TODO FMT _Fp should just be _Tp when to_chars has proper long double support.
+ _LIBCPP_HIDE_FROM_ABI __float_result __format_buffer(__float_buffer<_Fp>& __buffer, _Tp __value, bool __negative,
+ bool __has_precision) {
+ char* __first = __insert_sign(__buffer.begin(), __negative, this->__sign);
+ switch (this->__type) {
+ case _Flags::_Type::__default:
+ return __format_spec::__format_buffer_default(__buffer, __value, __first);
+
+ case _Flags::_Type::__float_hexadecimal_lower_case:
+ return __format_spec::__format_buffer_hexadecimal_lower_case(
+ __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first);
+
+ case _Flags::_Type::__float_hexadecimal_upper_case:
+ return __format_spec::__format_buffer_hexadecimal_upper_case(
+ __buffer, __value, __has_precision ? __buffer.__precision() : -1, __first);
+
+ case _Flags::_Type::__scientific_lower_case:
+ return __format_spec::__format_buffer_scientific_lower_case(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__scientific_upper_case:
+ return __format_spec::__format_buffer_scientific_upper_case(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__fixed_lower_case:
+ case _Flags::_Type::__fixed_upper_case:
+ return __format_spec::__format_buffer_fixed(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__general_lower_case:
+ return __format_spec::__format_buffer_general_lower_case(__buffer, __value, __buffer.__precision(), __first);
+
+ case _Flags::_Type::__general_upper_case:
+ return __format_spec::__format_buffer_general_upper_case(__buffer, __value, __buffer.__precision(), __first);
+
+ default:
+ _LIBCPP_ASSERT(false, "The parser should have validated the type");
+ _LIBCPP_UNREACHABLE();
+ }
+ }
+};
+
+} //namespace __format_spec
+
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<float, _CharT>
+ : public __format_spec::__formatter_floating_point<_CharT> {};
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<double, _CharT>
+ : public __format_spec::__formatter_floating_point<_CharT> {};
+template <__formatter::__char_type _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<long double, _CharT>
+ : public __format_spec::__formatter_floating_point<_CharT> {};
+
+# endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
+
+#endif //_LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___FORMAT_FORMATTER_FLOATING_POINT_H
diff --git a/libcxx/include/__format/formatter_integral.h b/libcxx/include/__format/formatter_integral.h
index 73e2fed8c0b7b..f164ee6109748 100644
--- a/libcxx/include/__format/formatter_integral.h
+++ b/libcxx/include/__format/formatter_integral.h
@@ -82,7 +82,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace __format_spec {
/** Wrapper around @ref to_chars, returning the output pointer. */
-template <class _Tp>
+template <integral _Tp>
_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last,
_Tp __value, int __base) {
// TODO FMT Evaluate code overhead due to not calling the internal function
diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index 6eae27d9ad188..75fc626c84ac1 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -475,6 +475,21 @@ __parse_type(const _CharT* __begin, _Flags& __flags) {
return ++__begin;
}
+/**
+ * Process the parsed alignment and zero-padding state of arithmetic types.
+ *
+ * [format.string.std]/13
+ * If the 0 character and an align option both appear, the 0 character is
+ * ignored.
+ *
+ * For the formatter a @ref __default alignment means zero-padding.
+ */
+_LIBCPP_HIDE_FROM_ABI constexpr void __process_arithmetic_alignment(_Flags& __flags) {
+ __flags.__zero_padding &= __flags.__alignment == _Flags::_Alignment::__default;
+ if (!__flags.__zero_padding && __flags.__alignment == _Flags::_Alignment::__default)
+ __flags.__alignment = _Flags::_Alignment::__right;
+}
+
/**
* The parser for the std-format-spec.
*
@@ -648,23 +663,9 @@ class _LIBCPP_TEMPLATE_VIS __parser_integral
return __begin;
}
- /**
- * Handles the post-parsing updates for the integer types.
- *
- * Updates the zero-padding and alignment for integer types.
- *
- * [format.string.std]/13
- * If the 0 character and an align option both appear, the 0 character is
- * ignored.
- *
- * For the formatter a @ref __default alignment means zero-padding. Update
- * the alignment based on parsed format string.
- */
+ /** Handles the post-parsing updates for the integer types. */
_LIBCPP_HIDE_FROM_ABI constexpr void __handle_integer() noexcept {
- this->__zero_padding &= this->__alignment == _Flags::_Alignment::__default;
- if (!this->__zero_padding &&
- this->__alignment == _Flags::_Alignment::__default)
- this->__alignment = _Flags::_Alignment::__right;
+ __process_arithmetic_alignment(static_cast<_Flags&>(*this));
}
/**
@@ -701,7 +702,130 @@ class _LIBCPP_TEMPLATE_VIS __parser_integral
}
};
-// 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 _CharT>
+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);
+ __process_arithmetic_alignment(static_cast<_Flags&>(*this));
+ __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;
+ }
+
+ /** 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
diff ers from the other types.
+ if (this->__has_precision_field())
+ this->__type = _Flags::_Type::__general_lower_case;
+ break;
+ 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()) {
+ // Set the default precision for the call to to_chars.
+ 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
index 788b9c299abc0..3a186469dd5c0 100644
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -277,6 +277,7 @@ namespace std {
#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
index a927f9d0e6700..c940a6d11d816 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -488,25 +488,26 @@ module std [system] {
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
index 0000000000000..35f19dcf76a73
--- /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
index 0000000000000..caf38a7e520a0
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_floating_point.pass.cpp
@@ -0,0 +1,353 @@
+//===----------------------------------------------------------------------===//
+// 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
+
+// <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 <format>
+#include <cassert>
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+# include <iostream>
+#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 <class CharT>
+using Parser = __parser_floating_point<CharT>;
+
+template <class CharT>
+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 <class CharT>
+constexpr void test(Expected<CharT> expected, size_t size, std::basic_string_view<CharT> fmt) {
+ // Initialize parser with sufficient arguments to avoid the parsing to fail
+ // due to insufficient arguments.
+ std::basic_format_parse_context<CharT> parse_ctx(fmt, std::__format::__number_max);
+ auto begin = parse_ctx.begin();
+ auto end = parse_ctx.end();
+ Parser<CharT> 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 <class CharT>
+constexpr void test(Expected<CharT> 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<CharT> fmt{f};
+ assert(fmt.back() == CharT('}') && "Pre-condition failure");
+
+ test(expected, size, fmt);
+ fmt.remove_suffix(1);
+ test(expected, size, fmt);
+}
+
+template <class CharT>
+constexpr void test() {
+ Parser<CharT> 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
diff er.
+ // 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<Parser<CharT>>("The format-spec fill field contains an invalid character", CSTR("{<"));
+ test_exception<Parser<CharT>>("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<Parser<CharT>>("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<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR("2147483648"));
+ test_exception<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR("5000000000"));
+ test_exception<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR("10000000000"));
+
+ test_exception<Parser<CharT>>("End of input while parsing format-spec arg-id", CSTR("{"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{0"));
+ test_exception<Parser<CharT>>("The arg-id of the format-spec starts with an invalid character", CSTR("{a"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{1"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR("{9:"));
+ test_exception<Parser<CharT>>("Invalid arg-id", 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<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR("{2147483648}"));
+ test_exception<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR("{5000000000}"));
+ test_exception<Parser<CharT>>("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<Parser<CharT>>("The format-spec precision field doesn't contain a value or arg-id", CSTR(".a"));
+ test_exception<Parser<CharT>>("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<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR(".2147483648"));
+ test_exception<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR(".5000000000"));
+ test_exception<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR(".10000000000"));
+
+ test_exception<Parser<CharT>>("End of input while parsing format-spec arg-id", CSTR(".{"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR(".{0"));
+ test_exception<Parser<CharT>>("The arg-id of the format-spec starts with an invalid character", CSTR(".{a"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR(".{1"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR(".{9"));
+ test_exception<Parser<CharT>>("Invalid arg-id", CSTR(".{9:"));
+ test_exception<Parser<CharT>>("Invalid arg-id", 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<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR(".{2147483648}"));
+ test_exception<Parser<CharT>>("The numeric value of the format-spec is too large", CSTR(".{5000000000}"));
+ test_exception<Parser<CharT>>("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<Parser<CharT>>(unsuported_type, CSTR("B}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("C}"));
+ test_exception<Parser<CharT>>(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<Parser<CharT>>(not_a_type, CSTR("H}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("I}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("J}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("K}"));
+ test({.locale_specific_form = true}, 1, CSTR("L}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("M}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("N}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("O}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("P}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("Q}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("R}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("S}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("T}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("U}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("V}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("W}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("X}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("Y}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("Z}"));
+
+ test({.type = _Flags::_Type::__float_hexadecimal_lower_case}, 1, CSTR("a}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("b}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("c}"));
+ test_exception<Parser<CharT>>(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<Parser<CharT>>(not_a_type, CSTR("h}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("i}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("j}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("k}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("l}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("m}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("n}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("o}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("p}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("q}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("r}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("s}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("t}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("u}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("v}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("w}"));
+ test_exception<Parser<CharT>>(unsuported_type, CSTR("x}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("y}"));
+ test_exception<Parser<CharT>>(not_a_type, CSTR("z}"));
+ }
+ // **** General ***
+ test_exception<Parser<CharT>>("The format-spec should consume the input or end with a '}'", CSTR("ss"));
+}
+
+constexpr bool test() {
+ test<char>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test<wchar_t>();
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+#if !defined(_WIN32) && !defined(_AIX)
+ // Make sure the parsers match the expectations. The layout of the
+ // subobjects is chosen to minimize the size required.
+ static_assert(sizeof(Parser<char>) == 3 * sizeof(uint32_t));
+# ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ static_assert(sizeof(Parser<wchar_t>) == (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
index 1ba1189b512c5..0e8e95d2762f6 100644
--- 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
// <format>
@@ -25,11 +24,14 @@
// - double
// - long double
-// TODO FMT Enable after floating-point support has been enabled
-#if 0
#include <format>
+
+#include <array>
#include <cassert>
+#include <cmath>
+#include <charconv>
#include <concepts>
+#include <string>
#include <type_traits>
#include "test_macros.h"
@@ -37,9 +39,8 @@
#define STR(S) MAKE_STRING(CharT, S)
-template <class StringViewT, class ArithmeticT>
-void test(StringViewT fmt, ArithmeticT arg) {
- using CharT = typename StringViewT::value_type;
+template <class CharT, class ArithmeticT>
+void test(std::basic_string_view<CharT> fmt, ArithmeticT arg, std::basic_string<CharT> expected) {
auto parse_ctx = std::basic_format_parse_context<CharT>(fmt);
std::formatter<ArithmeticT, CharT> formatter;
static_assert(std::semiregular<decltype(formatter)>);
@@ -51,15 +52,19 @@ void test(StringViewT fmt, ArithmeticT arg) {
auto out = std::back_inserter(result);
using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
- auto format_ctx = std::__format_context_create<decltype(out), CharT>(
- out, std::make_format_args<FormatCtxT>(arg));
+ auto format_ctx = std::__format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
formatter.format(arg, format_ctx);
- std::string expected = std::to_string(arg);
- assert(result == std::basic_string<CharT>(expected.begin(), expected.end()));
+
+ if (expected.empty()) {
+ std::array<char, 128> buffer;
+ expected.append(buffer.begin(), std::to_chars(buffer.begin(), buffer.end(), arg).ptr);
+ }
+
+ assert(result == expected);
}
template <class StringT, class ArithmeticT>
-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,40 +73,398 @@ void test_termination_condition(StringT f, ArithmeticT arg) {
std::basic_string_view<CharT> 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 <class CharT, class ArithmeticT>
+void test_hex_lower_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::hex, 20'000).ptr;
+ test_termination_condition(STR(".20000a}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000a}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000a}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000a}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000a}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::hex, 20'000).ptr;
+ test_termination_condition(STR(".20000La}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000La}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000La}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000La}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000La}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_hex_upper_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::hex, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000A}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000A}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000A}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000A}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000A}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::hex, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000LA}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000LA}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000LA}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000LA}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000LA}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_scientific_lower_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::scientific, 20'000).ptr;
+ test_termination_condition(STR(".20000e}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000e}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000e}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000e}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000e}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::scientific, 20'000).ptr;
+ test_termination_condition(STR(".20000Le}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000Le}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000Le}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000Le}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000Le}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_scientific_upper_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::scientific, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000E}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000E}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000E}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000E}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000E}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::scientific, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000LE}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000LE}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000LE}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000LE}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000LE}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_fixed_lower_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::fixed, 20'000).ptr;
+ test_termination_condition(STR(".20000f}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000f}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000f}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000f}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000f}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::fixed, 20'000).ptr;
+ test_termination_condition(STR(".20000Lf}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000Lf}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000Lf}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000Lf}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000Lf}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_fixed_upper_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::fixed, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000F}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000F}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000F}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000F}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000F}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::fixed, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000LF}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000LF}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000LF}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000LF}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000LF}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_general_lower_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::general, 20'000).ptr;
+ test_termination_condition(STR(".20000g}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000g}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000g}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000g}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000g}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::general, 20'000).ptr;
+ test_termination_condition(STR(".20000Lg}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000Lg}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000Lg}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000Lg}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000Lg}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_general_upper_case_precision(ArithmeticT value) {
+ std::array<char, 25'000> buffer;
+ char* end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::general, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000G}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size_t size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000G}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000G}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000G}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000G}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#ifndef _LIBCPP_HAS_NO_LOCALIZATION
+ end = std::to_chars(buffer.begin(), buffer.end(), value, std::chars_format::general, 20'000).ptr;
+ std::transform(buffer.begin(), end, buffer.begin(), [](char c) { return std::toupper(c); });
+ test_termination_condition(STR(".20000LG}"), value, std::basic_string<CharT>{buffer.begin(), end});
+
+ size = buffer.end() - end;
+ std::fill_n(end, size, '#');
+ test_termination_condition(STR("#<25000.20000LG}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - (size / 2), buffer.end());
+ test_termination_condition(STR("#^25000.20000LG}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::rotate(buffer.begin(), buffer.end() - ((size + 1) / 2), buffer.end());
+ test_termination_condition(STR("#>25000.20000LG}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+ std::fill_n(buffer.begin(), size, '0');
+ if (std::signbit(value)) {
+ buffer[0] = '-';
+ buffer[size] = '0';
+ }
+ test_termination_condition(STR("025000.20000LG}"), value, std::basic_string<CharT>{buffer.begin(), buffer.end()});
+#endif
+}
+
+template <class CharT, class ArithmeticT>
+void test_value(ArithmeticT value) {
+ test_hex_lower_case_precision<CharT>(value);
+ test_hex_upper_case_precision<CharT>(value);
+
+ test_scientific_lower_case_precision<CharT>(value);
+ test_scientific_upper_case_precision<CharT>(value);
+
+ test_fixed_lower_case_precision<CharT>(value);
+ test_fixed_upper_case_precision<CharT>(value);
+
+ test_general_lower_case_precision<CharT>(value);
+ test_general_upper_case_precision<CharT>(value);
+}
+
+template <class ArithmeticT, class CharT>
+void test_special_values() {
+ using A = ArithmeticT;
+
+ test_value<CharT>(-std::numeric_limits<A>::max());
+ test_value<CharT>(A(-1.0));
+ test_value<CharT>(-std::numeric_limits<A>::min());
+ test_value<CharT>(-std::numeric_limits<A>::denorm_min());
+ test_value<CharT>(A(-0.0));
+
+ test_value<CharT>(A(0.0));
+ test_value<CharT>(std::numeric_limits<A>::denorm_min());
+ test_value<CharT>(A(1.0));
+ test_value<CharT>(std::numeric_limits<A>::min());
+ test_value<CharT>(std::numeric_limits<A>::max());
}
template <class ArithmeticT, class CharT>
void test_float_type() {
using A = ArithmeticT;
+
test_termination_condition(STR("}"), A(-std::numeric_limits<float>::max()));
test_termination_condition(STR("}"), A(-std::numeric_limits<float>::min()));
test_termination_condition(STR("}"), A(-0.0));
+
test_termination_condition(STR("}"), A(0.0));
test_termination_condition(STR("}"), A(std::numeric_limits<float>::min()));
test_termination_condition(STR("}"), A(std::numeric_limits<float>::max()));
if (sizeof(A) > sizeof(float)) {
- test_termination_condition(STR("}"),
- A(-std::numeric_limits<double>::max()));
- test_termination_condition(STR("}"),
- A(-std::numeric_limits<double>::min()));
+ test_termination_condition(STR("}"), A(-std::numeric_limits<double>::max()));
+ test_termination_condition(STR("}"), A(-std::numeric_limits<double>::min()));
test_termination_condition(STR("}"), A(std::numeric_limits<double>::min()));
test_termination_condition(STR("}"), A(std::numeric_limits<double>::max()));
}
if (sizeof(A) > sizeof(double)) {
- test_termination_condition(STR("}"),
- A(-std::numeric_limits<long double>::max()));
- test_termination_condition(STR("}"),
- A(-std::numeric_limits<long double>::min()));
- test_termination_condition(STR("}"),
- A(std::numeric_limits<long double>::min()));
- test_termination_condition(STR("}"),
- A(std::numeric_limits<long double>::max()));
+ test_termination_condition(STR("}"), A(-std::numeric_limits<long double>::max()));
+ test_termination_condition(STR("}"), A(-std::numeric_limits<long double>::min()));
+ test_termination_condition(STR("}"), A(std::numeric_limits<long double>::min()));
+ test_termination_condition(STR("}"), A(std::numeric_limits<long double>::max()));
}
- // TODO FMT Also test with special floating point values: +/-Inf NaN.
+ // The results of inf and nan may
diff er from the result of to_chars.
+ test_termination_condition(STR("}"), A(-std::numeric_limits<A>::infinity()), STR("-inf"));
+ test_termination_condition(STR("}"), A(std::numeric_limits<A>::infinity()), STR("inf"));
+
+ A nan = std::numeric_limits<A>::quiet_NaN();
+ test_termination_condition(STR("}"), std::copysign(nan, -1.0), STR("-nan"));
+ test_termination_condition(STR("}"), nan, STR("nan"));
+
+ // TODO FMT Enable long double testing
+ if constexpr (!std::same_as<A, long double>)
+ test_special_values<A, CharT>();
}
template <class CharT>
@@ -119,6 +482,3 @@ int main(int, char**) {
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
index 470da03b8b083..c2eeb236f99d0 100644
--- a/libcxx/test/std/utilities/format/format.functions/format_tests.h
+++ b/libcxx/test/std/utilities/format/format.functions/format_tests.h
@@ -13,6 +13,8 @@
#include "make_string.h"
#include "test_macros.h"
+#include <cmath>
+
// 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...)
@@ -992,6 +994,1496 @@ void format_test_char_as_integer(TestFunction check,
fmt, '*');
}
+template <class F, class CharT, class TestFunction>
+void format_test_floating_point_hex_lower_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
+ auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan"
+
+ // Test whether the hexadecimal letters are the proper case.
+ // The precision is too large for float, so two tests are used.
+ check(STR("answer is '1.abcp+0'"), STR("answer is '{:a}'"), F(0x1.abcp+0));
+ check(STR("answer is '1.defp+0'"), STR("answer is '{:a}'"), F(0x1.defp+0));
+
+ // *** 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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6a}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7a}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: a}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: a}'"), -std::numeric_limits<F>::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 precision 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 '1p+1'"), STR("answer is '{:.0a}'"), F(2.5));
+ check(STR("answer is '1.p+1'"), STR("answer is '{:#.0a}'"), F(2.5));
+ 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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#a}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010a}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010a}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_hex_upper_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::quiet_NaN(); // "nan"
+ auto nan_neg = std::copysign(nan_pos, -1.0); // "-nan"
+
+ // Test whether the hexadecimal letters are the proper case.
+ // The precision is too large for float, so two tests are used.
+ check(STR("answer is '1.ABCP+0'"), STR("answer is '{:A}'"), F(0x1.abcp+0));
+ check(STR("answer is '1.DEFP+0'"), STR("answer is '{:A}'"), F(0x1.defp+0));
+
+ // *** 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<F>::infinity());
+ check(STR("answer is 'INF***'"), STR("answer is '{:*<6A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*INF**'"), STR("answer is '{:*^6A}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-INF'"), STR("answer is '{:#>7A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF###'"), STR("answer is '{:#<7A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-INF##'"), STR("answer is '{:#^7A}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF'"), STR("answer is '{:-A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+INF'"), STR("answer is '{:+A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: A}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-INF'"), STR("answer is '{:A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:-A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:+A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{: A}'"), -std::numeric_limits<F>::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 precision 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 '1P+1'"), STR("answer is '{:.0A}'"), F(2.5));
+ check(STR("answer is '1.P+1'"), STR("answer is '{:#.0A}'"), F(2.5));
+ 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<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:#A}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{:-010A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +INF'"), STR("answer is '{:+010A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: 010A}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -INF'"), STR("answer is '{:010A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:-010A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:+010A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{: 010A}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_hex_lower_case_precision(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6.6a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6.6a}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7.6a}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-.6a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+.6a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: .6a}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: .6a}'"), -std::numeric_limits<F>::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 ***
+ 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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#.6a}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010.6a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010.6a}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010.6a}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010.6a}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010.6a}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_hex_upper_case_precision(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF***'"), STR("answer is '{:*<6.6A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*INF**'"), STR("answer is '{:*^6.6A}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-INF'"), STR("answer is '{:#>7.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF###'"), STR("answer is '{:#<7.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-INF##'"), STR("answer is '{:#^7.6A}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF'"), STR("answer is '{:-.6A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+INF'"), STR("answer is '{:+.6A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: .6A}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-INF'"), STR("answer is '{:.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:-.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:+.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{: .6A}'"), -std::numeric_limits<F>::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 ***
+ 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<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:#.6A}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{:-010.6A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +INF'"), STR("answer is '{:+010.6A}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: 010.6A}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -INF'"), STR("answer is '{:010.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:-010.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:+010.6A}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{: 010.6A}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_scientific_lower_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6e}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6e}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7e}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-e}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+e}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: e}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: e}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#e}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010e}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010e}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010e}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010e}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010e}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_scientific_upper_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF***'"), STR("answer is '{:*<6E}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*INF**'"), STR("answer is '{:*^6E}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-INF'"), STR("answer is '{:#>7E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF###'"), STR("answer is '{:#<7E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-INF##'"), STR("answer is '{:#^7E}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF'"), STR("answer is '{:-E}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+INF'"), STR("answer is '{:+E}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: E}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-INF'"), STR("answer is '{:E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:-E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:+E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{: E}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:#E}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{:-010E}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +INF'"), STR("answer is '{:+010E}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: 010E}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -INF'"), STR("answer is '{:010E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:-010E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:+010E}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{: 010E}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_fixed_lower_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6f}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6f}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7f}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-f}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+f}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: f}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: f}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#f}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010f}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010f}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010f}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010f}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010f}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_fixed_upper_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF***'"), STR("answer is '{:*<6F}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*INF**'"), STR("answer is '{:*^6F}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-INF'"), STR("answer is '{:#>7F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF###'"), STR("answer is '{:#<7F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-INF##'"), STR("answer is '{:#^7F}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF'"), STR("answer is '{:-F}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+INF'"), STR("answer is '{:+F}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: F}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-INF'"), STR("answer is '{:F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:-F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:+F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{: F}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:#F}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{:-010F}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +INF'"), STR("answer is '{:+010F}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: 010F}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -INF'"), STR("answer is '{:010F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:-010F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:+010F}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{: 010F}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_general_lower_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6g}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6g}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7g}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-g}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+g}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: g}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: g}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#g}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010g}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010g}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010g}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010g}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010g}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_general_upper_case(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF***'"), STR("answer is '{:*<6G}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*INF**'"), STR("answer is '{:*^6G}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-INF'"), STR("answer is '{:#>7G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF###'"), STR("answer is '{:#<7G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-INF##'"), STR("answer is '{:#^7G}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'INF'"), STR("answer is '{:-G}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+INF'"), STR("answer is '{:+G}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: G}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-INF'"), STR("answer is '{:G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:-G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:+G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{: G}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-INF'"), STR("answer is '{:#G}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{:-010G}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +INF'"), STR("answer is '{:+010G}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' INF'"), STR("answer is '{: 010G}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -INF'"), STR("answer is '{:010G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:-010G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{:+010G}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -INF'"), STR("answer is '{: 010G}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_default(TestFunction check) {
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: }'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: }'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction>
+void format_test_floating_point_default_precision(TestFunction check) {
+
+ auto nan_pos = std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf***'"), STR("answer is '{:*<6.6}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '*inf**'"), STR("answer is '{:*^6.6}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '###-inf'"), STR("answer is '{:#>7.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf###'"), STR("answer is '{:#<7.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '#-inf##'"), STR("answer is '{:#^7.6}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is 'inf'"), STR("answer is '{:-.6}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is '+inf'"), STR("answer is '{:+.6}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: .6}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is '-inf'"), STR("answer is '{:.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:-.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:+.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{: .6}'"), -std::numeric_limits<F>::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 precision 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<F>::infinity());
+ check(STR("answer is '-inf'"), STR("answer is '{:#.6}'"), -std::numeric_limits<F>::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<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{:-010.6}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' +inf'"), STR("answer is '{:+010.6}'"), std::numeric_limits<F>::infinity());
+ check(STR("answer is ' inf'"), STR("answer is '{: 010.6}'"), std::numeric_limits<F>::infinity());
+
+ check(STR("answer is ' -inf'"), STR("answer is '{:010.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:-010.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{:+010.6}'"), -std::numeric_limits<F>::infinity());
+ check(STR("answer is ' -inf'"), STR("answer is '{: 010.6}'"), -std::numeric_limits<F>::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 <class F, class CharT, class TestFunction, class ExceptionTest>
+void format_test_floating_point(TestFunction check, ExceptionTest check_exception) {
+ format_test_floating_point_hex_lower_case<F, CharT>(check);
+ format_test_floating_point_hex_upper_case<F, CharT>(check);
+ format_test_floating_point_hex_lower_case_precision<F, CharT>(check);
+ format_test_floating_point_hex_upper_case_precision<F, CharT>(check);
+
+ format_test_floating_point_scientific_lower_case<F, CharT>(check);
+ format_test_floating_point_scientific_upper_case<F, CharT>(check);
+
+ format_test_floating_point_fixed_lower_case<F, CharT>(check);
+ format_test_floating_point_fixed_upper_case<F, CharT>(check);
+
+ format_test_floating_point_general_lower_case<F, CharT>(check);
+ format_test_floating_point_general_upper_case<F, CharT>(check);
+
+ format_test_floating_point_default<F, CharT>(check);
+ format_test_floating_point_default_precision<F, CharT>(check);
+
+ // *** type ***
+ for (const auto& fmt : invalid_types<CharT>("aAeEfFgG"))
+ check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, F(1));
+}
+
+template <class CharT, class TestFunction, class ExceptionTest>
+void format_test_floating_point(TestFunction check, ExceptionTest check_exception) {
+ format_test_floating_point<float, CharT>(check, check_exception);
+ format_test_floating_point<double, CharT>(check, check_exception);
+ format_test_floating_point<long double, CharT>(check, check_exception);
+}
+
template <class CharT, class TestFunction, class ExceptionTest>
void format_tests(TestFunction check, ExceptionTest check_exception) {
// *** Test escaping ***
@@ -1115,12 +2607,10 @@ void format_tests(TestFunction check, ExceptionTest check_exception) {
format_test_unsigned_integer<CharT>(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<float>(42));
- check(STR("hello 42.000000"), STR("hello {}"), static_cast<double>(42));
- check(STR("hello 42.000000"), STR("hello {}"), static_cast<long double>(42));
-#endif
+ check(STR("hello 42"), STR("hello {}"), static_cast<float>(42));
+ check(STR("hello 42"), STR("hello {}"), static_cast<double>(42));
+ check(STR("hello 42"), STR("hello {}"), static_cast<long double>(42));
+ format_test_floating_point<CharT>(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
index 7fe6907f2f4bd..5d86e46be7e6b 100644
--- 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
@@ -110,6 +110,7 @@ struct numpunct<char> : std::numpunct<char> {
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
@@ -120,6 +121,7 @@ struct numpunct<wchar_t> : std::numpunct<wchar_t> {
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
@@ -607,10 +609,1725 @@ void test_integer() {
test(STR("-0X004_A"), loc, STR("{:#08LX}"), -0x4a);
}
+template <class F, class CharT>
+void test_floating_point_hex_lower_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_hex_upper_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_hex_lower_case_precision() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_hex_upper_case_precision() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_scientific_lower_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_scientific_upper_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_fixed_lower_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_fixed_upper_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_general_lower_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_general_upper_case() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_default() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT>
+void test_floating_point_default_precision() {
+ std::locale loc = std::locale(std::locale(), new numpunct<CharT>());
+ 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 <class F, class CharT >
+void test_floating_point() {
+ test_floating_point_hex_lower_case<F, CharT>();
+ test_floating_point_hex_upper_case<F, CharT>();
+ test_floating_point_hex_lower_case_precision<F, CharT>();
+ test_floating_point_hex_upper_case_precision<F, CharT>();
+
+ test_floating_point_scientific_lower_case<F, CharT>();
+ test_floating_point_scientific_upper_case<F, CharT>();
+
+ test_floating_point_fixed_lower_case<F, CharT>();
+ test_floating_point_fixed_upper_case<F, CharT>();
+
+ test_floating_point_general_lower_case<F, CharT>();
+ test_floating_point_general_upper_case<F, CharT>();
+
+ test_floating_point_default<F, CharT>();
+ test_floating_point_default_precision<F, CharT>();
+}
+
template <class CharT>
void test() {
test_bool<CharT>();
test_integer<CharT>();
+ test_floating_point<float, CharT>();
+ test_floating_point<double, CharT>();
+ test_floating_point<long double, CharT>();
}
int main(int, char**) {
More information about the libcxx-commits
mailing list