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