]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/20_util/to_chars/long_double.cc
libstdc++: Add floating-point std::to_chars implementation
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / to_chars / long_double.cc
CommitLineData
3c57e692
PP
1// Copyright (C) 2020 Free Software Foundation, Inc.
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.
20// { dg-do run { target c++17 } }
21// { dg-xfail-run-if "Ryu needs __int128" { large_long_double && { ! int128 } } }
22
23#include <charconv>
24
25#include <cmath>
26#include <cstring>
27#include <iterator>
28#include <limits>
29
30#include <testsuite_hooks.h>
31
32using namespace std;
33
34// The long double overloads of std::to_chars currently just go through printf
35// (except for the hexadecimal formatting).
36
37// Test our hand-written hexadecimal formatting implementation.
38void
39test01()
40{
41 const long double hex_testcases[]
42 = { nextdownl(numeric_limits<long double>::max()),
43 nextupl(numeric_limits<long double>::min()),
44 42.0L,
45 0x1.2p+0L,
46 0x1.23p+0L,
47 0x1.234p+0L,
48 0x1.2345p+0L,
49 0x1.23456p+0L,
50 0x1.234567p+0L,
51 0x1.2345678p+0L,
52 0x1.23456789p+0L,
53 0x1.23456789p+0L,
54 0x1.23456789ap+0L,
55 0x1.23456789abp+0L,
56 0x1.23456789abcp+0L,
57 0x1.23456789abcdp+0L,
58 0x1.23456789abcdep+0L,
59 0x1.23456789abcdefp+0L,
60 0x1.23456789abcdef0p+0L,
61 0x1.23456789abcdef01p+0L,
62 0x1.23456789abcdef012p+0L,
63 0x1.23456789abcdef0123p+0L,
64 0x1.23456789abcdef01234p+0L,
65 0x1.23456789abcdef012345p+0L,
66 0x1.23456789abcdef0123456p+0L,
67 0x1.23456789abcdef01234567p+0L,
68 0x1.23456789abcdef012345678p+0L,
69 0x1.23456789abcdef0123456789p+0L,
70 0x1.23456789abcdef0123456789ap+0L,
71 0x1.23456789abcdef0123456789abp+0L,
72 0x1.23456789abcdef0123456789abcp+0L,
73 0x1.23456789abcdef0123456789abcdp+0L,
74 };
75
76 for (int exponent : {-11000, -3000, -300, -50, -7, 0, 7, 50, 300, 3000, 11000})
77 for (long double testcase : hex_testcases)
78 {
79 testcase = ldexpl(testcase, exponent);
80 if (testcase == 0.0L || isinf(testcase))
81 continue;
82
83 char to_chars_buffer[1024], printf_buffer[1024];
84 memset(to_chars_buffer, '\0', sizeof(to_chars_buffer));
85 memset(printf_buffer, '\0', sizeof(printf_buffer));
86
87 auto result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
88 testcase, chars_format::hex);
89 VERIFY( result.ec == errc{} );
90 *result.ptr = '\0';
91 sprintf(printf_buffer, "%La", testcase);
92 VERIFY( !strcmp(to_chars_buffer, printf_buffer+strlen("0x")) );
93
94 {
95 // Verify that the nearby values have a different shortest form.
96 testcase = nextdownl(testcase);
97 result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
98 testcase, chars_format::hex);
99 VERIFY( result.ec == errc{} );
100 *result.ptr = '\0';
101 VERIFY( strcmp(to_chars_buffer, printf_buffer+strlen("0x")) != 0);
102 sprintf(printf_buffer, "%La", testcase);
103 VERIFY( !strcmp(to_chars_buffer, printf_buffer+strlen("0x")) );
104
105 testcase = nextupl(nextupl(testcase));
106 result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
107 testcase, chars_format::hex);
108 VERIFY( result.ec == errc{} );
109 *result.ptr = '\0';
110 VERIFY( strcmp(to_chars_buffer, printf_buffer+strlen("0x")) != 0);
111 sprintf(printf_buffer, "%La", testcase);
112 VERIFY( !strcmp(to_chars_buffer, printf_buffer+strlen("0x")) );
113
114 testcase = nextdownl(testcase);
115 }
116
117 for (int precision = -1; precision < 50; precision++)
118 {
119 result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
120 testcase, chars_format::hex, precision);
121 VERIFY( result.ec == errc{} );
122 *result.ptr = '\0';
123 sprintf(printf_buffer, "%.*La", precision, testcase);
124 VERIFY( !strcmp(to_chars_buffer, printf_buffer+strlen("0x")) );
125 }
126 }
127}
128
129// Test the rest of the formatting modes, which go through printf.
130void
131test02()
132{
133 const long double growth_factor = 1.442695040888963407359924681001892137L;
134 for (chars_format fmt : {chars_format::fixed, chars_format::scientific,
135 chars_format::general})
136 for (long double __value = 1.0L, count = 0; !isinf(__value);
137 ++count <= 100.0L ? __value *= growth_factor : __value *= __value)
138 for (const long double value : {__value, 1.0L/__value})
139 {
140 for (const int precision : {-1, 0, 10, 100, 10000})
141 {
142 const char* const printf_specifier
143 = (fmt == chars_format::fixed ? "%.*Lf"
144 : fmt == chars_format::scientific ? "%.*Le"
145 : fmt == chars_format::general ? "%.*Lg"
146 : nullptr);
147 unsigned output_length = snprintf(nullptr, 0, printf_specifier,
148 precision, value);
149
150 char printf_buffer[output_length+1];
151 snprintf(printf_buffer, output_length+1, printf_specifier,
152 precision, value);
153
154 char to_chars_buffer[output_length];
155 auto result = to_chars(to_chars_buffer,
156 to_chars_buffer+output_length,
157 value, fmt, precision);
158 VERIFY( result.ec == errc{} );
159 VERIFY( !memcmp(printf_buffer, to_chars_buffer, output_length) );
160
161 result = to_chars(to_chars_buffer,
162 to_chars_buffer+output_length-1,
163 value, fmt, precision);
164 VERIFY( result.ec == errc::value_too_large );
165 }
166
167 // Verify that the nearby values have a different shortest form.
168 char to_chars_buffer[50000];
169 auto result = to_chars(begin(to_chars_buffer), end(to_chars_buffer),
170 value, fmt);
171 VERIFY( result.ec == errc{} );
172 *result.ptr = '\0';
173 char nearby_buffer[50000];
174 {
175 const long double smaller = nextdownl(value);
176 result = to_chars(begin(nearby_buffer), end(nearby_buffer),
177 smaller, fmt);
178 VERIFY( result.ec == errc{} );
179 *result.ptr = '\0';
180 VERIFY( strcmp(to_chars_buffer, nearby_buffer) != 0 );
181 }
182
183 {
184 long double larger = nextupl(value);
185 result = to_chars(begin(nearby_buffer), end(nearby_buffer),
186 larger, fmt);
187 VERIFY( result.ec == errc{} );
188 *result.ptr = '\0';
189 VERIFY( strcmp(to_chars_buffer, nearby_buffer) != 0 );
190 }
191 }
192}
193
194int
195main()
196{
197 test01();
198 test02();
199}