]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/20_util/to_chars/long_double.cc
libstdc++: Update ppc64le baseline_symbols.txt
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / to_chars / long_double.cc
CommitLineData
99dee823 1// Copyright (C) 2020-2021 Free Software Foundation, Inc.
3c57e692
PP
2//
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)
7// any later version.
8
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.
13
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/>.
17
18// <charconv> is supported in C++14 as a GNU extension, but this test uses C++17
19// hexadecimal floating-point literals.
ca4641a3
PP
20
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
29// overloads.
30// { dg-do run { target { c++17 && large_long_double } } }
31// { dg-do compile { target { c++17 && { ! large_long_double } } } }
32
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* } }
36
6a31d47e 37// { dg-require-effective-target ieee-floats }
3c57e692
PP
38
39#include <charconv>
40
41#include <cmath>
42#include <cstring>
43#include <iterator>
70aa0e6e 44#include <optional>
3c57e692
PP
45#include <limits>
46
47#include <testsuite_hooks.h>
48
49using namespace std;
50
19f3c433
PP
51namespace detail
52{
53 long double
54 nextupl(long double x)
55 { return nexttowardl(x, numeric_limits<long double>::infinity()); }
56
57 long double
58 nextdownl(long double x)
59 { return nexttowardl(x, -numeric_limits<long double>::infinity()); }
60}
61
3c57e692
PP
62// The long double overloads of std::to_chars currently just go through printf
63// (except for the hexadecimal formatting).
64
65// Test our hand-written hexadecimal formatting implementation.
66void
67test01()
68{
70aa0e6e
PP
69 // Verifies correctness of the hexadecimal form [BEGIN,END) for VALUE by
70 // round-tripping it through from_chars (if available).
71 auto verify_via_from_chars = [] (char *begin, char *end, long double value) {
72#if __cpp_lib_to_chars >= 201611L || _GLIBCXX_HAVE_USELOCALE
73 long double roundtrip;
74 auto result = from_chars(begin, end, roundtrip, chars_format::hex);
75 VERIFY( result.ec == errc{} );
76 VERIFY( result.ptr == end );
77 VERIFY( roundtrip == value );
78#endif
79 };
80
81 // Verifies correctness of the null-terminated hexadecimal form at BEGIN
82 // for VALUE and PRECISION by comparing it with the output of printf's %La
83 // conversion specifier.
84 auto verify_via_printf = [] (char *begin, long double value,
85 optional<int> precision = nullopt) {
86 char printf_buffer[1024] = {};
87 if (precision.has_value())
88 sprintf(printf_buffer, "%.*La", precision.value(), value);
89 else
90 sprintf(printf_buffer, "%La", value);
91
92 // Only compare with the output of printf if the leading hex digits agree.
93 // If the leading hex digit of our form doesn't agree with that of printf,
94 // then the two forms may still be equivalent (e.g. 1.1p+0 vs 8.8p-3). But
95 // if the leading hex digits do agree, then we do expect the two forms to be
96 // the same.
97 if (printf_buffer[strlen("0x")] == begin[0])
98 VERIFY( !strcmp(begin, printf_buffer+strlen("0x")) );
99 };
100
3c57e692 101 const long double hex_testcases[]
19f3c433
PP
102 = { detail::nextdownl(numeric_limits<long double>::max()),
103 detail::nextupl(numeric_limits<long double>::min()),
3c57e692
PP
104 42.0L,
105 0x1.2p+0L,
106 0x1.23p+0L,
107 0x1.234p+0L,
108 0x1.2345p+0L,
109 0x1.23456p+0L,
110 0x1.234567p+0L,
111 0x1.2345678p+0L,
112 0x1.23456789p+0L,
113 0x1.23456789p+0L,
114 0x1.23456789ap+0L,
115 0x1.23456789abp+0L,
116 0x1.23456789abcp+0L,
117 0x1.23456789abcdp+0L,
118 0x1.23456789abcdep+0L,
119 0x1.23456789abcdefp+0L,
120 0x1.23456789abcdef0p+0L,
121 0x1.23456789abcdef01p+0L,
122 0x1.23456789abcdef012p+0L,
123 0x1.23456789abcdef0123p+0L,
124 0x1.23456789abcdef01234p+0L,
125 0x1.23456789abcdef012345p+0L,
126 0x1.23456789abcdef0123456p+0L,
127 0x1.23456789abcdef01234567p+0L,
128 0x1.23456789abcdef012345678p+0L,
129 0x1.23456789abcdef0123456789p+0L,
130 0x1.23456789abcdef0123456789ap+0L,
131 0x1.23456789abcdef0123456789abp+0L,
132 0x1.23456789abcdef0123456789abcp+0L,
133 0x1.23456789abcdef0123456789abcdp+0L,
134 };
135
136 for (int exponent : {-11000, -3000, -300, -50, -7, 0, 7, 50, 300, 3000, 11000})
137 for (long double testcase : hex_testcases)
138 {
139 testcase = ldexpl(testcase, exponent);
140 if (testcase == 0.0L || isinf(testcase))
141 continue;
142
70aa0e6e 143 char to_chars_buffer[1024] = {};
3c57e692
PP
144 auto result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
145 testcase, chars_format::hex);
146 VERIFY( result.ec == errc{} );
147 *result.ptr = '\0';
70aa0e6e
PP
148 verify_via_from_chars(begin(to_chars_buffer), result.ptr, testcase);
149 verify_via_printf(to_chars_buffer, testcase);
3c57e692 150
70aa0e6e
PP
151 // Verify the nearby values, and also check they have a different
152 // shortest form.
153 for (long double nearby
154 : { detail::nextdownl(testcase), detail::nextupl(testcase) })
3c57e692 155 {
70aa0e6e
PP
156 char nearby_buffer[1024] = {};
157 result = to_chars(begin(nearby_buffer), end(nearby_buffer),
158 nearby, chars_format::hex);
3c57e692
PP
159 VERIFY( result.ec == errc{} );
160 *result.ptr = '\0';
70aa0e6e
PP
161 VERIFY( strcmp(nearby_buffer, to_chars_buffer) != 0);
162 verify_via_from_chars(begin(nearby_buffer), result.ptr, nearby);
163 verify_via_printf(nearby_buffer, nearby);
3c57e692
PP
164 }
165
166 for (int precision = -1; precision < 50; precision++)
167 {
168 result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
169 testcase, chars_format::hex, precision);
170 VERIFY( result.ec == errc{} );
171 *result.ptr = '\0';
70aa0e6e 172 verify_via_printf(to_chars_buffer, testcase, precision);
3c57e692
PP
173 }
174 }
175}
176
177// Test the rest of the formatting modes, which go through printf.
178void
179test02()
180{
181 const long double growth_factor = 1.442695040888963407359924681001892137L;
182 for (chars_format fmt : {chars_format::fixed, chars_format::scientific,
183 chars_format::general})
184 for (long double __value = 1.0L, count = 0; !isinf(__value);
185 ++count <= 100.0L ? __value *= growth_factor : __value *= __value)
186 for (const long double value : {__value, 1.0L/__value})
187 {
188 for (const int precision : {-1, 0, 10, 100, 10000})
189 {
190 const char* const printf_specifier
191 = (fmt == chars_format::fixed ? "%.*Lf"
192 : fmt == chars_format::scientific ? "%.*Le"
193 : fmt == chars_format::general ? "%.*Lg"
194 : nullptr);
195 unsigned output_length = snprintf(nullptr, 0, printf_specifier,
196 precision, value);
197
198 char printf_buffer[output_length+1];
199 snprintf(printf_buffer, output_length+1, printf_specifier,
200 precision, value);
201
202 char to_chars_buffer[output_length];
203 auto result = to_chars(to_chars_buffer,
204 to_chars_buffer+output_length,
205 value, fmt, precision);
206 VERIFY( result.ec == errc{} );
207 VERIFY( !memcmp(printf_buffer, to_chars_buffer, output_length) );
208
209 result = to_chars(to_chars_buffer,
210 to_chars_buffer+output_length-1,
211 value, fmt, precision);
212 VERIFY( result.ec == errc::value_too_large );
213 }
214
215 // Verify that the nearby values have a different shortest form.
216 char to_chars_buffer[50000];
217 auto result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
218 value, fmt);
219 VERIFY( result.ec == errc{} );
220 *result.ptr = '\0';
221 char nearby_buffer[50000];
222 {
19f3c433 223 const long double smaller = detail::nextdownl(value);
3c57e692
PP
224 result = to_chars(begin(nearby_buffer), end(nearby_buffer),
225 smaller, fmt);
226 VERIFY( result.ec == errc{} );
227 *result.ptr = '\0';
228 VERIFY( strcmp(to_chars_buffer, nearby_buffer) != 0 );
229 }
230
231 {
19f3c433 232 long double larger = detail::nextupl(value);
3c57e692
PP
233 result = to_chars(begin(nearby_buffer), end(nearby_buffer),
234 larger, fmt);
235 VERIFY( result.ec == errc{} );
236 *result.ptr = '\0';
237 VERIFY( strcmp(to_chars_buffer, nearby_buffer) != 0 );
238 }
239 }
240}
241
242int
243main()
244{
245 test01();
246 test02();
247}