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