]>
git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/to_chars/long_double.cc
1 // Copyright (C) 2020-2022 Free Software Foundation, Inc.
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
18 // <charconv> is supported in C++14 as a GNU extension, but this test uses C++17
19 // hexadecimal floating-point literals.
21 // When long double is larger than double, the long double to_chars overloads
22 // are partially implemented in terms of printf, so this test in turn uses
23 // printf to verify correctness these overloads.
24 // When long double == double, the long double to_chars overloads are simple
25 // wrappers around the corresponding double overloads. Since they don't go
26 // through printf, we can't portably verify their output by comparing it with
27 // that of printf, so it's simplest to just not run this test on such targets;
28 // correctness of these overloads is already implied by that of the double
30 // { dg-do run { target { c++17 && large_long_double } } }
31 // { dg-do compile { target { c++17 && { ! large_long_double } } } }
33 // The system printf on these targets appear to be buggy. FIXME: Make this test
34 // more portable and robust to differences in system printf behavior.
35 // { dg-xfail-run-if "Non-conforming printf (see PR98384)" { *-*-solaris* *-*-darwin* } }
37 // { dg-require-effective-target ieee_floats }
38 // { dg-require-effective-target size32plus }
48 #include <testsuite_hooks.h>
55 nextupl(long double x
)
56 { return nexttowardl(x
, numeric_limits
<long double>::infinity()); }
59 nextdownl(long double x
)
60 { return nexttowardl(x
, -numeric_limits
<long double>::infinity()); }
63 // The long double overloads of std::to_chars currently just go through printf
64 // (except for the hexadecimal formatting).
66 // Test our hand-written hexadecimal formatting implementation.
70 // Verifies correctness of the hexadecimal form [BEGIN,END) for VALUE by
71 // round-tripping it through from_chars (if available).
72 auto verify_via_from_chars
= [] (char *begin
, char *end
, long double value
) {
73 #if __cpp_lib_to_chars >= 201611L
74 long double roundtrip
;
75 auto result
= from_chars(begin
, end
, roundtrip
, chars_format::hex
);
76 VERIFY( result
.ec
== errc
{} );
77 VERIFY( result
.ptr
== end
);
78 VERIFY( roundtrip
== value
);
82 // Verifies correctness of the null-terminated hexadecimal form at BEGIN
83 // for VALUE and PRECISION by comparing it with the output of printf's %La
84 // conversion specifier.
85 auto verify_via_printf
= [] (char *begin
, long double value
,
86 optional
<int> precision
= nullopt
) {
87 char printf_buffer
[1024] = {};
88 if (precision
.has_value())
89 sprintf(printf_buffer
, "%.*La", precision
.value(), value
);
91 sprintf(printf_buffer
, "%La", value
);
93 // Only compare with the output of printf if the leading hex digits agree.
94 // If the leading hex digit of our form doesn't agree with that of printf,
95 // then the two forms may still be equivalent (e.g. 1.1p+0 vs 8.8p-3). But
96 // if the leading hex digits do agree, then we do expect the two forms to be
98 if (printf_buffer
[strlen("0x")] == begin
[0])
99 VERIFY( !strcmp(begin
, printf_buffer
+strlen("0x")) );
102 const long double hex_testcases
[]
103 = { detail::nextdownl(numeric_limits
<long double>::max()),
104 detail::nextupl(numeric_limits
<long double>::min()),
118 0x1.23456789abcdp
+0L,
119 0x1.23456789abcdep
+0L,
120 0x1.23456789abcdefp
+0L,
121 0x1.23456789abcdef0p
+0L,
122 0x1.23456789abcdef01p
+0L,
123 0x1.23456789abcdef012p
+0L,
124 0x1.23456789abcdef0123p
+0L,
125 0x1.23456789abcdef01234p
+0L,
126 0x1.23456789abcdef012345p
+0L,
127 0x1.23456789abcdef0123456p
+0L,
128 0x1.23456789abcdef01234567p
+0L,
129 0x1.23456789abcdef012345678p
+0L,
130 0x1.23456789abcdef0123456789p
+0L,
131 0x1.23456789abcdef0123456789ap
+0L,
132 0x1.23456789abcdef0123456789abp
+0L,
133 0x1.23456789abcdef0123456789abcp
+0L,
134 0x1.23456789abcdef0123456789abcdp
+0L,
137 for (int exponent
: {-11000, -3000, -300, -50, -7, 0, 7, 50, 300, 3000, 11000})
138 for (long double testcase
: hex_testcases
)
140 testcase
= ldexpl(testcase
, exponent
);
141 if (testcase
== 0.0L || isinf(testcase
))
144 char to_chars_buffer
[1024] = {};
145 auto result
= to_chars(begin(to_chars_buffer
), end(to_chars_buffer
),
146 testcase
, chars_format::hex
);
147 VERIFY( result
.ec
== errc
{} );
149 verify_via_from_chars(begin(to_chars_buffer
), result
.ptr
, testcase
);
150 verify_via_printf(to_chars_buffer
, testcase
);
152 // Verify the nearby values, and also check they have a different
154 for (long double nearby
155 : { detail::nextdownl(testcase
), detail::nextupl(testcase
) })
157 char nearby_buffer
[1024] = {};
158 result
= to_chars(begin(nearby_buffer
), end(nearby_buffer
),
159 nearby
, chars_format::hex
);
160 VERIFY( result
.ec
== errc
{} );
162 VERIFY( strcmp(nearby_buffer
, to_chars_buffer
) != 0);
163 verify_via_from_chars(begin(nearby_buffer
), result
.ptr
, nearby
);
164 verify_via_printf(nearby_buffer
, nearby
);
167 for (int precision
= -1; precision
< 50; precision
++)
169 result
= to_chars(begin(to_chars_buffer
), end(to_chars_buffer
),
170 testcase
, chars_format::hex
, precision
);
171 VERIFY( result
.ec
== errc
{} );
173 verify_via_printf(to_chars_buffer
, testcase
, precision
);
178 // Test the rest of the formatting modes, which go through printf.
182 const long double growth_factor
= 1.442695040888963407359924681001892137L;
183 for (chars_format fmt
: {chars_format::fixed
, chars_format::scientific
,
184 chars_format::general
})
185 for (long double __value
= 1.0L, count
= 0; !isinf(__value
);
186 ++count
<= 100.0L ? __value
*= growth_factor
: __value
*= __value
)
187 for (const long double value
: {__value
, 1.0L/__value
})
189 for (const int precision
: {-1, 0, 10, 100, 10000})
191 const char* const printf_specifier
192 = (fmt
== chars_format::fixed
? "%.*Lf"
193 : fmt
== chars_format::scientific
? "%.*Le"
194 : fmt
== chars_format::general
? "%.*Lg"
196 unsigned output_length
= snprintf(nullptr, 0, printf_specifier
,
199 char printf_buffer
[output_length
+1];
200 snprintf(printf_buffer
, output_length
+1, printf_specifier
,
203 char to_chars_buffer
[output_length
];
204 auto result
= to_chars(to_chars_buffer
,
205 to_chars_buffer
+output_length
,
206 value
, fmt
, precision
);
207 VERIFY( result
.ec
== errc
{} );
208 VERIFY( !memcmp(printf_buffer
, to_chars_buffer
, output_length
) );
210 result
= to_chars(to_chars_buffer
,
211 to_chars_buffer
+output_length
-1,
212 value
, fmt
, precision
);
213 VERIFY( result
.ec
== errc::value_too_large
);
216 // Verify that the nearby values have a different shortest form.
217 char to_chars_buffer
[50000];
218 auto result
= to_chars(begin(to_chars_buffer
), end(to_chars_buffer
),
220 VERIFY( result
.ec
== errc
{} );
222 char nearby_buffer
[50000];
224 const long double smaller
= detail::nextdownl(value
);
225 result
= to_chars(begin(nearby_buffer
), end(nearby_buffer
),
227 VERIFY( result
.ec
== errc
{} );
229 VERIFY( strcmp(to_chars_buffer
, nearby_buffer
) != 0 );
233 long double larger
= detail::nextupl(value
);
234 result
= to_chars(begin(nearby_buffer
), end(nearby_buffer
),
236 VERIFY( result
.ec
== errc
{} );
238 VERIFY( strcmp(to_chars_buffer
, nearby_buffer
) != 0 );