diff --git a/stl/inc/xlocnum b/stl/inc/xlocnum index e2c887b5f1f..0c0bd1db376 100644 --- a/stl/inc/xlocnum +++ b/stl/inc/xlocnum @@ -1146,6 +1146,45 @@ __PURE_APPDOMAIN_GLOBAL locale::id num_get<_Elem, _InIt>::id; #pragma clang diagnostic pop #endif // __clang__ +// STRUCT TEMPLATE _Hex_float_precision +template +struct _Hex_float_precision; + +template <> +struct _Hex_float_precision { + // the number of hexits needed to represent (DBL_MANT_DIG - 1) bits after the radix point exactly + static constexpr int value = ((DBL_MANT_DIG - 1) + 3) / 4; +}; + +template <> +struct _Hex_float_precision { + // the number of hexits needed to represent (LDBL_MANT_DIG - 1) bits after the radix point exactly + static constexpr int value = ((LDBL_MANT_DIG - 1) + 3) / 4; +}; + +// FUNCTION TEMPLATE _Float_put_desired_precision +template +int _Float_put_desired_precision(const streamsize _Precision, const ios_base::fmtflags _Float_flags) { + const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific); + if (_Is_hex) { + return _Hex_float_precision<_Ty>::value; + } + + if (_Precision > 0) { + return static_cast(_Precision); + } else if (_Precision == 0) { + const bool _Is_default_float = _Float_flags == 0; + if (_Is_default_float) { + return 1; + } else { + return 0; + } + } else { + constexpr int _Default_precision = 6; + return _Default_precision; + } +} + // CLASS TEMPLATE num_put template >> class num_put : public locale::facet { // facet for converting encoded numbers to text @@ -1292,10 +1331,14 @@ protected: _OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, double _Val) const { // put formatted double to _Dest string _Buf; char _Fmt[8]; - bool _Isfixed = (_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed; - streamsize _Precision = _Iosbase.precision() <= 0 && !_Isfixed ? 6 : _Iosbase.precision(); // desired precision - size_t _Bufsize = static_cast(_Precision); - if (_Isfixed && 1e10 < _CSTD fabs(_Val)) { // f or F format + const auto _Float_flags = _Iosbase.flags() & ios_base::floatfield; + const bool _Is_fixed = _Float_flags == ios_base::fixed; + const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific); + const streamsize _Precision = _Is_hex ? -1 : _Iosbase.precision(); // precision setting + const int _Desired_precision = + _Float_put_desired_precision(_Precision, _Float_flags); // desired precision + size_t _Bufsize = static_cast(_Desired_precision); + if (_Is_fixed && 1e10 < _CSTD fabs(_Val)) { // f or F format int _Ptwo; (void) _CSTD frexp(_Val, &_Ptwo); _Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L; @@ -1312,10 +1355,14 @@ protected: _OutIt _Dest, ios_base& _Iosbase, _Elem _Fill, long double _Val) const { // put formatted long double to _Dest string _Buf; char _Fmt[8]; - bool _Isfixed = (_Iosbase.flags() & ios_base::floatfield) == ios_base::fixed; - streamsize _Precision = _Iosbase.precision() <= 0 && !_Isfixed ? 6 : _Iosbase.precision(); // desired precision - size_t _Bufsize = static_cast(_Precision); - if (_Isfixed && 1e10 < _CSTD fabsl(_Val)) { // f or F format + const auto _Float_flags = _Iosbase.flags() & ios_base::floatfield; + const bool _Is_fixed = _Float_flags == ios_base::fixed; + const bool _Is_hex = _Float_flags == (ios_base::fixed | ios_base::scientific); + const streamsize _Precision = _Is_hex ? -1 : _Iosbase.precision(); // precision setting + const int _Desired_precision = + _Float_put_desired_precision(_Precision, _Float_flags); // desired precision + size_t _Bufsize = static_cast(_Desired_precision); + if (_Is_fixed && 1e10 < _CSTD fabsl(_Val)) { // f or F format int _Ptwo; (void) _CSTD frexpl(_Val, &_Ptwo); _Bufsize += _CSTD abs(_Ptwo) * 30103L / 100000L; diff --git a/tests/tr1/tests/ostream1/test.cpp b/tests/tr1/tests/ostream1/test.cpp index f19c5727112..74bc1791572 100644 --- a/tests/tr1/tests/ostream1/test.cpp +++ b/tests/tr1/tests/ostream1/test.cpp @@ -213,9 +213,109 @@ void test_main() { // test basic workings of ostream definitions outs << STD hexfloat << 2.0; STD string ans = outs.str(); const char* buf = ans.c_str(); - CHECK_STR(buf, "0x1.000p+1"); + CHECK_STR(buf, "0x1.0000000000000p+1"); } + outs.precision(0); + + outs.str(""); + outs << STD defaultfloat << 1.5; + CHECK_STR(outs.str().c_str(), "2"); + + outs.str(""); + outs << STD fixed << 1.0; + CHECK_STR(outs.str().c_str(), "1"); + + outs.str(""); + outs << STD scientific << 2.0; + CHECK_STR(outs.str().c_str(), "2e+00"); + + outs.str(""); + outs << STD hexfloat << 2.0; + CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1"); + + outs.precision(-1); + + outs.str(""); + outs << STD defaultfloat << 1.5; + CHECK_STR(outs.str().c_str(), "1.5"); + + outs.str(""); + outs << STD fixed << 1.0; + CHECK_STR(outs.str().c_str(), "1.000000"); + + outs.str(""); + outs << STD scientific << 2.0; + CHECK_STR(outs.str().c_str(), "2.000000e+00"); + + outs.str(""); + outs << STD hexfloat << 2.0; + CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1"); + + outs.precision(-49); + outs.str(""); + outs << STD fixed << 1.0; + CHECK_STR(outs.str().c_str(), "1.000000"); + + outs.precision(3); + + outs.str(""); + outs << STD defaultfloat << 1.5L; + CHECK_STR(outs.str().c_str(), "1.5"); + + outs.str(""); + outs << STD fixed << 1.0L; + CHECK_STR(outs.str().c_str(), "1.000"); + + outs.str(""); + outs << STD scientific << 2.0L; + CHECK_STR(outs.str().c_str(), "2.000e+00"); + + outs.str(""); + outs << STD hexfloat << 2.0L; + CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1"); + + outs.precision(0); + + outs.str(""); + outs << STD defaultfloat << 1.5L; + CHECK_STR(outs.str().c_str(), "2"); + + outs.str(""); + outs << STD fixed << 1.0L; + CHECK_STR(outs.str().c_str(), "1"); + + outs.str(""); + outs << STD scientific << 2.0L; + CHECK_STR(outs.str().c_str(), "2e+00"); + + outs.str(""); + outs << STD hexfloat << 2.0L; + CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1"); + + outs.precision(-1); + + outs.str(""); + outs << STD defaultfloat << 1.5L; + CHECK_STR(outs.str().c_str(), "1.5"); + + outs.str(""); + outs << STD fixed << 1.0L; + CHECK_STR(outs.str().c_str(), "1.000000"); + + outs.str(""); + outs << STD scientific << 2.0L; + CHECK_STR(outs.str().c_str(), "2.000000e+00"); + + outs.str(""); + outs << STD hexfloat << 2.0L; + CHECK_STR(outs.str().c_str(), "0x1.0000000000000p+1"); + + outs.precision(-49); + outs.str(""); + outs << STD fixed << 1.0L; + CHECK_STR(outs.str().c_str(), "1.000000"); + // test Boolx inserter const Boolx no(0), yes(1); outs.str(""); diff --git a/tests/tr1/tests/ostream2/test.cpp b/tests/tr1/tests/ostream2/test.cpp index 4fe35d436db..6a2701ecb91 100644 --- a/tests/tr1/tests/ostream2/test.cpp +++ b/tests/tr1/tests/ostream2/test.cpp @@ -208,7 +208,107 @@ void test_main() { // test basic workings of ostream definitions outs << STD hexfloat << 2.0; STD wstring ans = outs.str(); const wchar_t* buf = ans.c_str(); - CHECK_WSTR(buf, L"0x1.000p+1"); + CHECK_WSTR(buf, L"0x1.0000000000000p+1"); + + outs.precision(0); + + outs.str(L""); + outs << STD defaultfloat << 1.5; + CHECK_WSTR(outs.str().c_str(), L"2"); + + outs.str(L""); + outs << STD fixed << 1.0; + CHECK_WSTR(outs.str().c_str(), L"1"); + + outs.str(L""); + outs << STD scientific << 2.0; + CHECK_WSTR(outs.str().c_str(), L"2e+00"); + + outs.str(L""); + outs << STD hexfloat << 2.0; + CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1"); + + outs.precision(-1); + + outs.str(L""); + outs << STD defaultfloat << 1.5; + CHECK_WSTR(outs.str().c_str(), L"1.5"); + + outs.str(L""); + outs << STD fixed << 1.0; + CHECK_WSTR(outs.str().c_str(), L"1.000000"); + + outs.str(L""); + outs << STD scientific << 2.0; + CHECK_WSTR(outs.str().c_str(), L"2.000000e+00"); + + outs.str(L""); + outs << STD hexfloat << 2.0; + CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1"); + + outs.precision(-49); + outs.str(L""); + outs << STD fixed << 1.0; + CHECK_WSTR(outs.str().c_str(), L"1.000000"); + + outs.precision(3); + + outs.str(L""); + outs << STD defaultfloat << 1.5L; + CHECK_WSTR(outs.str().c_str(), L"1.5"); + + outs.str(L""); + outs << STD fixed << 1.0L; + CHECK_WSTR(outs.str().c_str(), L"1.000"); + + outs.str(L""); + outs << STD scientific << 2.0L; + CHECK_WSTR(outs.str().c_str(), L"2.000e+00"); + + outs.str(L""); + outs << STD hexfloat << 2.0L; + CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1"); + + outs.precision(0); + + outs.str(L""); + outs << STD defaultfloat << 1.5L; + CHECK_WSTR(outs.str().c_str(), L"2"); + + outs.str(L""); + outs << STD fixed << 1.0L; + CHECK_WSTR(outs.str().c_str(), L"1"); + + outs.str(L""); + outs << STD scientific << 2.0L; + CHECK_WSTR(outs.str().c_str(), L"2e+00"); + + outs.str(L""); + outs << STD hexfloat << 2.0L; + CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1"); + + outs.precision(-1); + + outs.str(L""); + outs << STD defaultfloat << 1.5L; + CHECK_WSTR(outs.str().c_str(), L"1.5"); + + outs.str(L""); + outs << STD fixed << 1.0L; + CHECK_WSTR(outs.str().c_str(), L"1.000000"); + + outs.str(L""); + outs << STD scientific << 2.0L; + CHECK_WSTR(outs.str().c_str(), L"2.000000e+00"); + + outs.str(L""); + outs << STD hexfloat << 2.0L; + CHECK_WSTR(outs.str().c_str(), L"0x1.0000000000000p+1"); + + outs.precision(-49); + outs.str(L""); + outs << STD fixed << 1.0L; + CHECK_WSTR(outs.str().c_str(), L"1.000000"); // test Boolx inserter const Boolx no(0), yes(1);