xref: /llvm-project/flang/unittests/Runtime/NumericalFormatTest.cpp (revision c91ba04328e1ded6f284469a7828d181324d4e30)
1ffc67bb3SDavid Spickett //===-- flang/unittests/Runtime/NumericalFormatTest.cpp ---------*- C++ -*-===//
2ffc67bb3SDavid Spickett //
3ffc67bb3SDavid Spickett // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ffc67bb3SDavid Spickett // See https://llvm.org/LICENSE.txt for license information.
5ffc67bb3SDavid Spickett // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ffc67bb3SDavid Spickett //
7ffc67bb3SDavid Spickett //===----------------------------------------------------------------------===//
8ffc67bb3SDavid Spickett 
9ffc67bb3SDavid Spickett #include "CrashHandlerFixture.h"
10ffc67bb3SDavid Spickett #include "flang/Runtime/descriptor.h"
11*c91ba043SMichael Kruse #include "flang/Runtime/io-api-consts.h"
12ffc67bb3SDavid Spickett #include <algorithm>
13ffc67bb3SDavid Spickett #include <array>
14ffc67bb3SDavid Spickett #include <cstring>
15ffc67bb3SDavid Spickett #include <gtest/gtest.h>
16ffc67bb3SDavid Spickett #include <tuple>
17ffc67bb3SDavid Spickett 
18ffc67bb3SDavid Spickett using namespace Fortran::runtime;
19ffc67bb3SDavid Spickett using namespace Fortran::runtime::io;
20ffc67bb3SDavid Spickett 
21ffc67bb3SDavid Spickett static bool CompareFormattedStrings(
22ffc67bb3SDavid Spickett     const std::string &expect, const std::string &got) {
23ffc67bb3SDavid Spickett   std::string want{expect};
24ffc67bb3SDavid Spickett   want.resize(got.size(), ' ');
25ffc67bb3SDavid Spickett   return want == got;
26ffc67bb3SDavid Spickett }
27ffc67bb3SDavid Spickett 
28ffc67bb3SDavid Spickett static bool CompareFormattedStrings(
29ffc67bb3SDavid Spickett     const char *expect, const std::string &&got) {
30ffc67bb3SDavid Spickett   return CompareFormattedStrings(std::string(expect), std::move(got));
31ffc67bb3SDavid Spickett }
32ffc67bb3SDavid Spickett 
33ffc67bb3SDavid Spickett // Perform format and compare the result with expected value
34ffc67bb3SDavid Spickett static bool CompareFormatReal(
35ffc67bb3SDavid Spickett     const char *format, double x, const char *expect, std::string &got) {
36ffc67bb3SDavid Spickett   char buffer[800];
37ffc67bb3SDavid Spickett   auto cookie{IONAME(BeginInternalFormattedOutput)(
38ffc67bb3SDavid Spickett       buffer, sizeof buffer, format, std::strlen(format))};
39ffc67bb3SDavid Spickett   EXPECT_TRUE(IONAME(OutputReal64)(cookie, x));
40ffc67bb3SDavid Spickett   auto status{IONAME(EndIoStatement)(cookie)};
41ffc67bb3SDavid Spickett   EXPECT_EQ(status, 0);
42ffc67bb3SDavid Spickett   got = std::string{buffer, sizeof buffer};
43ffc67bb3SDavid Spickett   auto lastNonBlank{got.find_last_not_of(" ")};
44ffc67bb3SDavid Spickett   if (lastNonBlank != std::string::npos) {
45ffc67bb3SDavid Spickett     got.resize(lastNonBlank + 1);
46ffc67bb3SDavid Spickett   }
47ffc67bb3SDavid Spickett   return CompareFormattedStrings(expect, got);
48ffc67bb3SDavid Spickett }
49ffc67bb3SDavid Spickett 
50ffc67bb3SDavid Spickett // Convert raw uint64 into double, perform format, and compare with expected
51ffc67bb3SDavid Spickett static bool CompareFormatReal(const char *format, std::uint64_t xInt,
52ffc67bb3SDavid Spickett     const char *expect, std::string &got) {
53ffc67bb3SDavid Spickett   double x;
54ffc67bb3SDavid Spickett   static_assert(sizeof(double) == sizeof(std::uint64_t),
55ffc67bb3SDavid Spickett       "Size of double != size of uint64_t!");
56ffc67bb3SDavid Spickett   std::memcpy(&x, &xInt, sizeof xInt);
57ffc67bb3SDavid Spickett   return CompareFormatReal(format, x, expect, got);
58ffc67bb3SDavid Spickett }
59ffc67bb3SDavid Spickett 
60ffc67bb3SDavid Spickett static bool CompareFormatInteger(
61ffc67bb3SDavid Spickett     const char *format, std::int64_t x, const char *expect, std::string &got) {
62ffc67bb3SDavid Spickett   char buffer[800];
63ffc67bb3SDavid Spickett   auto cookie{IONAME(BeginInternalFormattedOutput)(
64ffc67bb3SDavid Spickett       buffer, sizeof buffer, format, std::strlen(format))};
65ffc67bb3SDavid Spickett   EXPECT_TRUE(IONAME(OutputInteger64)(cookie, x));
66ffc67bb3SDavid Spickett   auto status{IONAME(EndIoStatement)(cookie)};
67ffc67bb3SDavid Spickett   EXPECT_EQ(status, 0);
68ffc67bb3SDavid Spickett   got = std::string{buffer, sizeof buffer};
69ffc67bb3SDavid Spickett   auto lastNonBlank{got.find_last_not_of(" ")};
70ffc67bb3SDavid Spickett   if (lastNonBlank != std::string::npos) {
71ffc67bb3SDavid Spickett     got.resize(lastNonBlank + 1);
72ffc67bb3SDavid Spickett   }
73ffc67bb3SDavid Spickett   return CompareFormattedStrings(expect, got);
74ffc67bb3SDavid Spickett }
75ffc67bb3SDavid Spickett 
76ffc67bb3SDavid Spickett struct IOApiTests : CrashHandlerFixture {};
77ffc67bb3SDavid Spickett 
78ffc67bb3SDavid Spickett TEST(IOApiTests, HelloWorldOutputTest) {
79ffc67bb3SDavid Spickett   static constexpr int bufferSize{32};
80ffc67bb3SDavid Spickett   char buffer[bufferSize];
81ffc67bb3SDavid Spickett 
82ffc67bb3SDavid Spickett   // Create format for all types and values to be written
83ffc67bb3SDavid Spickett   const char *format{"(6HHELLO,,A6,2X,I3,1X,'0x',Z8,1X,L1)"};
84ffc67bb3SDavid Spickett   auto cookie{IONAME(BeginInternalFormattedOutput)(
85ffc67bb3SDavid Spickett       buffer, bufferSize, format, std::strlen(format))};
86ffc67bb3SDavid Spickett 
87ffc67bb3SDavid Spickett   // Write string, integer, and logical values to buffer
88ffc67bb3SDavid Spickett   IONAME(OutputAscii)(cookie, "WORLD", 5);
89ffc67bb3SDavid Spickett   IONAME(OutputInteger64)(cookie, 678);
90ffc67bb3SDavid Spickett   IONAME(OutputInteger32)(cookie, 0xfeedface);
91ffc67bb3SDavid Spickett   IONAME(OutputLogical)(cookie, true);
92ffc67bb3SDavid Spickett 
93ffc67bb3SDavid Spickett   // Ensure IO succeeded
94ffc67bb3SDavid Spickett   auto status{IONAME(EndIoStatement)(cookie)};
95ffc67bb3SDavid Spickett   ASSERT_EQ(status, 0) << "hello: '" << format << "' failed, status "
96ffc67bb3SDavid Spickett                        << static_cast<int>(status);
97ffc67bb3SDavid Spickett 
98ffc67bb3SDavid Spickett   // Ensure final buffer matches expected string output
99ffc67bb3SDavid Spickett   static const std::string expect{"HELLO, WORLD  678 0xFEEDFACE T"};
100ffc67bb3SDavid Spickett   ASSERT_TRUE(
101ffc67bb3SDavid Spickett       CompareFormattedStrings(expect, std::string{buffer, sizeof buffer}))
102ffc67bb3SDavid Spickett       << "Expected '" << expect << "', got " << buffer;
103ffc67bb3SDavid Spickett }
104ffc67bb3SDavid Spickett 
105ffc67bb3SDavid Spickett TEST(IOApiTests, MultilineOutputTest) {
106ffc67bb3SDavid Spickett   // Allocate buffer for multiline output
107ffc67bb3SDavid Spickett   static constexpr int numLines{5};
108ffc67bb3SDavid Spickett   static constexpr int lineLength{32};
109ffc67bb3SDavid Spickett   char buffer[numLines][lineLength];
110ffc67bb3SDavid Spickett 
111ffc67bb3SDavid Spickett   // Create descriptor for entire buffer
112ffc67bb3SDavid Spickett   static constexpr int staticDescriptorMaxRank{1};
113ffc67bb3SDavid Spickett   StaticDescriptor<staticDescriptorMaxRank> wholeStaticDescriptor;
114ffc67bb3SDavid Spickett   Descriptor &whole{wholeStaticDescriptor.descriptor()};
115ffc67bb3SDavid Spickett   static const SubscriptValue extent[]{numLines};
116ffc67bb3SDavid Spickett   whole.Establish(TypeCode{CFI_type_char}, /*elementBytes=*/lineLength, &buffer,
117ffc67bb3SDavid Spickett       staticDescriptorMaxRank, extent, CFI_attribute_pointer);
118ffc67bb3SDavid Spickett   whole.Dump(stderr);
119ffc67bb3SDavid Spickett   whole.Check();
120ffc67bb3SDavid Spickett 
121ffc67bb3SDavid Spickett   // Create descriptor for buffer section
122ffc67bb3SDavid Spickett   StaticDescriptor<staticDescriptorMaxRank> sectionStaticDescriptor;
123ffc67bb3SDavid Spickett   Descriptor &section{sectionStaticDescriptor.descriptor()};
124ffc67bb3SDavid Spickett   static const SubscriptValue lowers[]{0}, uppers[]{4}, strides[]{1};
125ffc67bb3SDavid Spickett   section.Establish(whole.type(), /*elementBytes=*/whole.ElementBytes(),
126ffc67bb3SDavid Spickett       nullptr, /*maxRank=*/staticDescriptorMaxRank, extent,
127ffc67bb3SDavid Spickett       CFI_attribute_pointer);
128ffc67bb3SDavid Spickett 
129ffc67bb3SDavid Spickett   // Ensure C descriptor address `section.raw()` is updated without error
130ffc67bb3SDavid Spickett   const auto error{
131ffc67bb3SDavid Spickett       CFI_section(&section.raw(), &whole.raw(), lowers, uppers, strides)};
132ffc67bb3SDavid Spickett   ASSERT_EQ(error, 0) << "multiline: CFI_section failed: " << error;
133ffc67bb3SDavid Spickett   section.Dump(stderr);
134ffc67bb3SDavid Spickett   section.Check();
135ffc67bb3SDavid Spickett 
136ffc67bb3SDavid Spickett   // Create format string and initialize IO operation
137ffc67bb3SDavid Spickett   const char *format{
138ffc67bb3SDavid Spickett       "('?abcde,',T1,'>',T9,A,TL12,A,TR25,'<'//G0,17X,'abcd',1(2I4))"};
139ffc67bb3SDavid Spickett   auto cookie{IONAME(BeginInternalArrayFormattedOutput)(
140ffc67bb3SDavid Spickett       section, format, std::strlen(format))};
141ffc67bb3SDavid Spickett 
142ffc67bb3SDavid Spickett   // Fill last line with periods
143ffc67bb3SDavid Spickett   std::memset(buffer[numLines - 1], '.', lineLength);
144ffc67bb3SDavid Spickett 
145ffc67bb3SDavid Spickett   // Write data to buffer
146ffc67bb3SDavid Spickett   IONAME(OutputAscii)(cookie, "WORLD", 5);
147ffc67bb3SDavid Spickett   IONAME(OutputAscii)(cookie, "HELLO", 5);
148ffc67bb3SDavid Spickett   IONAME(OutputInteger64)(cookie, 789);
149ffc67bb3SDavid Spickett   for (int j{666}; j <= 999; j += 111) {
150ffc67bb3SDavid Spickett     IONAME(OutputInteger64)(cookie, j);
151ffc67bb3SDavid Spickett   }
152ffc67bb3SDavid Spickett 
153ffc67bb3SDavid Spickett   // Ensure no errors occured in write operations above
154ffc67bb3SDavid Spickett   const auto status{IONAME(EndIoStatement)(cookie)};
155ffc67bb3SDavid Spickett   ASSERT_EQ(status, 0) << "multiline: '" << format << "' failed, status "
156ffc67bb3SDavid Spickett                        << static_cast<int>(status);
157ffc67bb3SDavid Spickett 
158ffc67bb3SDavid Spickett   static const std::string expect{">HELLO, WORLD                  <"
159ffc67bb3SDavid Spickett                                   "                                "
160ffc67bb3SDavid Spickett                                   "789                 abcd 666 777"
161ffc67bb3SDavid Spickett                                   " 888 999                        "
162ffc67bb3SDavid Spickett                                   "................................"};
163ffc67bb3SDavid Spickett   // Ensure formatted string matches expected output
164ffc67bb3SDavid Spickett   EXPECT_TRUE(
165ffc67bb3SDavid Spickett       CompareFormattedStrings(expect, std::string{buffer[0], sizeof buffer}))
166ffc67bb3SDavid Spickett       << "Expected '" << expect << "' but got '"
167ffc67bb3SDavid Spickett       << std::string{buffer[0], sizeof buffer} << "'";
168ffc67bb3SDavid Spickett }
169ffc67bb3SDavid Spickett 
170ffc67bb3SDavid Spickett TEST(IOApiTests, ListInputTest) {
171ffc67bb3SDavid Spickett   static const char input[]{",1*,(5.,6.),(7.0,8.0)"};
172ffc67bb3SDavid Spickett   auto cookie{IONAME(BeginInternalListInput)(input, sizeof input - 1)};
173ffc67bb3SDavid Spickett 
174ffc67bb3SDavid Spickett   // Create real values for IO tests
175ffc67bb3SDavid Spickett   static constexpr int numRealValues{8};
176ffc67bb3SDavid Spickett   float z[numRealValues];
177ffc67bb3SDavid Spickett   for (int j{0}; j < numRealValues; ++j) {
178ffc67bb3SDavid Spickett     z[j] = -(j + 1);
179ffc67bb3SDavid Spickett   }
180ffc67bb3SDavid Spickett 
181ffc67bb3SDavid Spickett   // Ensure reading complex values to floats does not result in an error
182ffc67bb3SDavid Spickett   for (int j{0}; j < numRealValues; j += 2) {
183ffc67bb3SDavid Spickett     ASSERT_TRUE(IONAME(InputComplex32)(cookie, &z[j]))
184ffc67bb3SDavid Spickett         << "InputComplex32 failed with value " << z[j];
185ffc67bb3SDavid Spickett   }
186ffc67bb3SDavid Spickett 
187ffc67bb3SDavid Spickett   // Ensure no IO errors occured during IO operations above
188ffc67bb3SDavid Spickett   auto status{IONAME(EndIoStatement)(cookie)};
189ffc67bb3SDavid Spickett   ASSERT_EQ(status, 0) << "Failed complex list-directed input, status "
190ffc67bb3SDavid Spickett                        << static_cast<int>(status);
191ffc67bb3SDavid Spickett 
192ffc67bb3SDavid Spickett   // Ensure writing complex values from floats does not result in an error
193ffc67bb3SDavid Spickett   static constexpr int bufferSize{39};
194ffc67bb3SDavid Spickett   char output[bufferSize];
195ffc67bb3SDavid Spickett   output[bufferSize - 1] = '\0';
196ffc67bb3SDavid Spickett   cookie = IONAME(BeginInternalListOutput)(output, bufferSize - 1);
197ffc67bb3SDavid Spickett   for (int j{0}; j < numRealValues; j += 2) {
198ffc67bb3SDavid Spickett     ASSERT_TRUE(IONAME(OutputComplex32)(cookie, z[j], z[j + 1]))
199ffc67bb3SDavid Spickett         << "OutputComplex32 failed when outputting value " << z[j] << ", "
200ffc67bb3SDavid Spickett         << z[j + 1];
201ffc67bb3SDavid Spickett   }
202ffc67bb3SDavid Spickett 
203ffc67bb3SDavid Spickett   // Ensure no IO errors occured during IO operations above
204ffc67bb3SDavid Spickett   status = IONAME(EndIoStatement)(cookie);
205ffc67bb3SDavid Spickett   ASSERT_EQ(status, 0) << "Failed complex list-directed output, status "
206ffc67bb3SDavid Spickett                        << static_cast<int>(status);
207ffc67bb3SDavid Spickett 
208ffc67bb3SDavid Spickett   // Verify output buffer against expected value
209ffc67bb3SDavid Spickett   static const char expect[bufferSize]{
210ffc67bb3SDavid Spickett       " (-1.,-2.) (-3.,-4.) (5.,6.) (7.,8.)  "};
211ffc67bb3SDavid Spickett   ASSERT_EQ(std::strncmp(output, expect, bufferSize), 0)
212ffc67bb3SDavid Spickett       << "Failed complex list-directed output, expected '" << expect
213ffc67bb3SDavid Spickett       << "', but got '" << output << "'";
214ffc67bb3SDavid Spickett }
215ffc67bb3SDavid Spickett 
216ffc67bb3SDavid Spickett TEST(IOApiTests, DescriptorOutputTest) {
217ffc67bb3SDavid Spickett   static constexpr int bufferSize{10};
218ffc67bb3SDavid Spickett   char buffer[bufferSize];
219ffc67bb3SDavid Spickett   const char *format{"(2A4)"};
220ffc67bb3SDavid Spickett   auto cookie{IONAME(BeginInternalFormattedOutput)(
221ffc67bb3SDavid Spickett       buffer, bufferSize, format, std::strlen(format))};
222ffc67bb3SDavid Spickett 
223ffc67bb3SDavid Spickett   // Create descriptor for output
224ffc67bb3SDavid Spickett   static constexpr int staticDescriptorMaxRank{1};
225ffc67bb3SDavid Spickett   StaticDescriptor<staticDescriptorMaxRank> staticDescriptor;
226ffc67bb3SDavid Spickett   Descriptor &desc{staticDescriptor.descriptor()};
227ffc67bb3SDavid Spickett   static constexpr int subscriptExtent{2};
228ffc67bb3SDavid Spickett   static const SubscriptValue extent[]{subscriptExtent};
229ffc67bb3SDavid Spickett 
230ffc67bb3SDavid Spickett   // Manually write to descriptor buffer
231ffc67bb3SDavid Spickett   static constexpr int dataLength{4};
232ffc67bb3SDavid Spickett   char data[subscriptExtent][dataLength];
233ffc67bb3SDavid Spickett   std::memcpy(data[0], "ABCD", dataLength);
234ffc67bb3SDavid Spickett   std::memcpy(data[1], "EFGH", dataLength);
235ffc67bb3SDavid Spickett   desc.Establish(TypeCode{CFI_type_char}, dataLength, &data,
236ffc67bb3SDavid Spickett       staticDescriptorMaxRank, extent);
237ffc67bb3SDavid Spickett   desc.Dump(stderr);
238ffc67bb3SDavid Spickett   desc.Check();
239ffc67bb3SDavid Spickett   IONAME(OutputDescriptor)(cookie, desc);
240ffc67bb3SDavid Spickett 
241ffc67bb3SDavid Spickett   // Ensure no errors were encountered in initializing the cookie and descriptor
242ffc67bb3SDavid Spickett   auto formatStatus{IONAME(EndIoStatement)(cookie)};
243ffc67bb3SDavid Spickett   ASSERT_EQ(formatStatus, 0)
244ffc67bb3SDavid Spickett       << "descrOutputTest: '" << format << "' failed, status "
245ffc67bb3SDavid Spickett       << static_cast<int>(formatStatus);
246ffc67bb3SDavid Spickett 
247ffc67bb3SDavid Spickett   // Ensure buffer matches expected output
248ffc67bb3SDavid Spickett   EXPECT_TRUE(
249ffc67bb3SDavid Spickett       CompareFormattedStrings("ABCDEFGH  ", std::string{buffer, sizeof buffer}))
250ffc67bb3SDavid Spickett       << "descrOutputTest: formatted: got '"
251ffc67bb3SDavid Spickett       << std::string{buffer, sizeof buffer} << "'";
252ffc67bb3SDavid Spickett 
253ffc67bb3SDavid Spickett   // Begin list-directed output on cookie by descriptor
254ffc67bb3SDavid Spickett   cookie = IONAME(BeginInternalListOutput)(buffer, sizeof buffer);
255ffc67bb3SDavid Spickett   IONAME(OutputDescriptor)(cookie, desc);
256ffc67bb3SDavid Spickett 
257ffc67bb3SDavid Spickett   // Ensure list-directed output does not result in an IO error
258ffc67bb3SDavid Spickett   auto listDirectedStatus{IONAME(EndIoStatement)(cookie)};
259ffc67bb3SDavid Spickett   ASSERT_EQ(listDirectedStatus, 0)
260ffc67bb3SDavid Spickett       << "descrOutputTest: list-directed failed, status "
261ffc67bb3SDavid Spickett       << static_cast<int>(listDirectedStatus);
262ffc67bb3SDavid Spickett 
263ffc67bb3SDavid Spickett   // Ensure buffer matches expected output
264ffc67bb3SDavid Spickett   EXPECT_TRUE(
265ffc67bb3SDavid Spickett       CompareFormattedStrings(" ABCDEFGH ", std::string{buffer, sizeof buffer}))
266ffc67bb3SDavid Spickett       << "descrOutputTest: list-directed: got '"
267ffc67bb3SDavid Spickett       << std::string{buffer, sizeof buffer} << "'";
268ffc67bb3SDavid Spickett }
269ffc67bb3SDavid Spickett 
270ffc67bb3SDavid Spickett //------------------------------------------------------------------------------
271ffc67bb3SDavid Spickett /// Tests for output formatting real values
272ffc67bb3SDavid Spickett //------------------------------------------------------------------------------
273ffc67bb3SDavid Spickett 
274ffc67bb3SDavid Spickett TEST(IOApiTests, FormatZeroes) {
275ffc67bb3SDavid Spickett   static constexpr std::pair<const char *, const char *> zeroes[]{
276ffc67bb3SDavid Spickett       {"(E32.17,';')", "         0.00000000000000000E+00;"},
277ffc67bb3SDavid Spickett       {"(F32.17,';')", "             0.00000000000000000;"},
278ffc67bb3SDavid Spickett       {"(G32.17,';')", "          0.0000000000000000    ;"},
279ffc67bb3SDavid Spickett       {"(DC,E32.17,';')", "         0,00000000000000000E+00;"},
280ffc67bb3SDavid Spickett       {"(DC,F32.17,';')", "             0,00000000000000000;"},
281ffc67bb3SDavid Spickett       {"(DC,G32.17,';')", "          0,0000000000000000    ;"},
282ffc67bb3SDavid Spickett       {"(D32.17,';')", "         0.00000000000000000D+00;"},
283ffc67bb3SDavid Spickett       {"(E32.17E1,';')", "          0.00000000000000000E+0;"},
284ffc67bb3SDavid Spickett       {"(G32.17E1,';')", "           0.0000000000000000   ;"},
285ffc67bb3SDavid Spickett       {"(E32.17E0,';')", "          0.00000000000000000E+0;"},
286ffc67bb3SDavid Spickett       {"(G32.17E0,';')", "          0.0000000000000000    ;"},
287ffc67bb3SDavid Spickett       {"(1P,E32.17,';')", "         0.00000000000000000E+00;"},
288ffc67bb3SDavid Spickett       {"(1PE32.17,';')", "         0.00000000000000000E+00;"}, // no comma
289ffc67bb3SDavid Spickett       {"(1P,F32.17,';')", "             0.00000000000000000;"},
290ffc67bb3SDavid Spickett       {"(1P,G32.17,';')", "          0.0000000000000000    ;"},
291ffc67bb3SDavid Spickett       {"(2P,E32.17,';')", "         00.0000000000000000E+00;"},
292ffc67bb3SDavid Spickett       {"(-1P,E32.17,';')", "         0.00000000000000000E+00;"},
293ea7e50cdSPeter Klausler       {"(EX32.17,';')", "        0X0.00000000000000000P+0;"},
294ea7e50cdSPeter Klausler       {"(DC,EX32.17,';')", "        0X0,00000000000000000P+0;"},
295ffc67bb3SDavid Spickett       {"(G0,';')", "0.;"},
296ffc67bb3SDavid Spickett   };
297ffc67bb3SDavid Spickett 
298ffc67bb3SDavid Spickett   for (auto const &[format, expect] : zeroes) {
299ffc67bb3SDavid Spickett     std::string got;
300ffc67bb3SDavid Spickett     ASSERT_TRUE(CompareFormatReal(format, 0.0, expect, got))
301ffc67bb3SDavid Spickett         << "Failed to format " << format << ", expected '" << expect
302ffc67bb3SDavid Spickett         << "', got '" << got << "'";
303ffc67bb3SDavid Spickett   }
304ffc67bb3SDavid Spickett }
305ffc67bb3SDavid Spickett 
306ffc67bb3SDavid Spickett TEST(IOApiTests, FormatOnes) {
307ffc67bb3SDavid Spickett   static constexpr std::pair<const char *, const char *> ones[]{
308ffc67bb3SDavid Spickett       {"(E32.17,';')", "         0.10000000000000000E+01;"},
309ffc67bb3SDavid Spickett       {"(F32.17,';')", "             1.00000000000000000;"},
310ffc67bb3SDavid Spickett       {"(G32.17,';')", "          1.0000000000000000    ;"},
311ffc67bb3SDavid Spickett       {"(E32.17E1,';')", "          0.10000000000000000E+1;"},
312ffc67bb3SDavid Spickett       {"(G32.17E1,';')", "           1.0000000000000000   ;"},
313ffc67bb3SDavid Spickett       {"(E32.17E0,';')", "          0.10000000000000000E+1;"},
314ffc67bb3SDavid Spickett       {"(G32.17E0,';')", "          1.0000000000000000    ;"},
315ffc67bb3SDavid Spickett       {"(E32.17E4,';')", "       0.10000000000000000E+0001;"},
316ffc67bb3SDavid Spickett       {"(G32.17E4,';')", "        1.0000000000000000      ;"},
317ffc67bb3SDavid Spickett       {"(1P,E32.17,';')", "         1.00000000000000000E+00;"},
318ffc67bb3SDavid Spickett       {"(1PE32.17,';')", "         1.00000000000000000E+00;"}, // no comma
319ffc67bb3SDavid Spickett       {"(1P,F32.17,';')", "            10.00000000000000000;"},
320ffc67bb3SDavid Spickett       {"(1P,G32.17,';')", "          1.0000000000000000    ;"},
321ffc67bb3SDavid Spickett       {"(ES32.17,';')", "         1.00000000000000000E+00;"},
322ffc67bb3SDavid Spickett       {"(2P,E32.17,';')", "         10.0000000000000000E-01;"},
323ffc67bb3SDavid Spickett       {"(2P,G32.17,';')", "          1.0000000000000000    ;"},
324ffc67bb3SDavid Spickett       {"(-1P,E32.17,';')", "         0.01000000000000000E+02;"},
325ffc67bb3SDavid Spickett       {"(-1P,G32.17,';')", "          1.0000000000000000    ;"},
326ea7e50cdSPeter Klausler       {"(EX32.17,';')", "        0X8.00000000000000000P-3;"},
327ea7e50cdSPeter Klausler       {"(DC,EX32.17,';')", "        0X8,00000000000000000P-3;"},
328ffc67bb3SDavid Spickett       {"(G0,';')", "1.;"},
329ffc67bb3SDavid Spickett   };
330ffc67bb3SDavid Spickett 
331ffc67bb3SDavid Spickett   for (auto const &[format, expect] : ones) {
332ffc67bb3SDavid Spickett     std::string got;
333ffc67bb3SDavid Spickett     ASSERT_TRUE(CompareFormatReal(format, 1.0, expect, got))
334ffc67bb3SDavid Spickett         << "Failed to format " << format << ", expected '" << expect
335ffc67bb3SDavid Spickett         << "', got '" << got << "'";
336ffc67bb3SDavid Spickett   }
337ffc67bb3SDavid Spickett }
338ffc67bb3SDavid Spickett 
339ffc67bb3SDavid Spickett TEST(IOApiTests, FormatNegativeOnes) {
340ffc67bb3SDavid Spickett   static constexpr std::tuple<const char *, const char *> negOnes[]{
341ffc67bb3SDavid Spickett       {"(E32.17,';')", "        -0.10000000000000000E+01;"},
342ffc67bb3SDavid Spickett       {"(F32.17,';')", "            -1.00000000000000000;"},
343ffc67bb3SDavid Spickett       {"(G32.17,';')", "         -1.0000000000000000    ;"},
344ea7e50cdSPeter Klausler       {"(EX32.17,';')", "       -0X8.00000000000000000P-3;"},
345ffc67bb3SDavid Spickett       {"(G0,';')", "-1.;"},
346ffc67bb3SDavid Spickett   };
347ffc67bb3SDavid Spickett   for (auto const &[format, expect] : negOnes) {
348ffc67bb3SDavid Spickett     std::string got;
349ffc67bb3SDavid Spickett     ASSERT_TRUE(CompareFormatReal(format, -1.0, expect, got))
350ffc67bb3SDavid Spickett         << "Failed to format " << format << ", expected '" << expect
351ffc67bb3SDavid Spickett         << "', got '" << got << "'";
352ffc67bb3SDavid Spickett   }
353ffc67bb3SDavid Spickett }
354ffc67bb3SDavid Spickett 
355ffc67bb3SDavid Spickett // Each test case contains a raw uint64, a format string for a real value, and
356ffc67bb3SDavid Spickett // the expected resulting string from formatting the raw uint64. The double
357ffc67bb3SDavid Spickett // representation of the uint64 is commented above each test case.
358ffc67bb3SDavid Spickett TEST(IOApiTests, FormatDoubleValues) {
359ffc67bb3SDavid Spickett 
360ffc67bb3SDavid Spickett   using TestCaseTy = std::tuple<std::uint64_t,
361ffc67bb3SDavid Spickett       std::vector<std::tuple<const char *, const char *>>>;
362ffc67bb3SDavid Spickett   static const std::vector<TestCaseTy> testCases{
363ffc67bb3SDavid Spickett       {// -0
364ffc67bb3SDavid Spickett           0x8000000000000000,
365ffc67bb3SDavid Spickett           {
366ffc67bb3SDavid Spickett               {"(E9.1,';')", " -0.0E+00;"},
367ffc67bb3SDavid Spickett               {"(F4.0,';')", " -0.;"},
368ffc67bb3SDavid Spickett               {"(F0.1,';')", "-.0;"},
369ffc67bb3SDavid Spickett               {"(G8.0,';')", "-0.0E+00;"},
370ffc67bb3SDavid Spickett               {"(G8.1,';')", " -0.    ;"},
371ffc67bb3SDavid Spickett               {"(G0,';')", "-0.;"},
372ffc67bb3SDavid Spickett               {"(E9.1,';')", " -0.0E+00;"},
373ea7e50cdSPeter Klausler               {"(EX9.1,';')", "-0X0.0P+0;"},
374ffc67bb3SDavid Spickett           }},
375ffc67bb3SDavid Spickett       {// +Inf
376ffc67bb3SDavid Spickett           0x7ff0000000000000,
377ffc67bb3SDavid Spickett           {
378ffc67bb3SDavid Spickett               {"(E9.1,';')", "      Inf;"},
379ffc67bb3SDavid Spickett               {"(F9.1,';')", "      Inf;"},
380ffc67bb3SDavid Spickett               {"(G9.1,';')", "      Inf;"},
381ea7e50cdSPeter Klausler               {"(EX9.1,';')", "      Inf;"},
382ffc67bb3SDavid Spickett               {"(SP,E9.1,';')", "     +Inf;"},
383ffc67bb3SDavid Spickett               {"(SP,F9.1,';')", "     +Inf;"},
384ffc67bb3SDavid Spickett               {"(SP,G9.1,';')", "     +Inf;"},
385ea7e50cdSPeter Klausler               {"(SP,EX9.1,';')", "     +Inf;"},
386ffc67bb3SDavid Spickett               {"(G0,';')", "Inf;"},
387ffc67bb3SDavid Spickett           }},
388ffc67bb3SDavid Spickett       {// -Inf
389ffc67bb3SDavid Spickett           0xfff0000000000000,
390ffc67bb3SDavid Spickett           {
391ffc67bb3SDavid Spickett               {"(E9.1,';')", "     -Inf;"},
392ffc67bb3SDavid Spickett               {"(F9.1,';')", "     -Inf;"},
393ffc67bb3SDavid Spickett               {"(G9.1,';')", "     -Inf;"},
394ea7e50cdSPeter Klausler               {"(EX9.1,';')", "     -Inf;"},
395ffc67bb3SDavid Spickett               {"(G0,';')", "-Inf;"},
396ffc67bb3SDavid Spickett           }},
397ffc67bb3SDavid Spickett       {// NaN
398ffc67bb3SDavid Spickett           0x7ff0000000000001,
399ffc67bb3SDavid Spickett           {
400ffc67bb3SDavid Spickett               {"(E9.1,';')", "      NaN;"},
401ffc67bb3SDavid Spickett               {"(F9.1,';')", "      NaN;"},
402ffc67bb3SDavid Spickett               {"(G9.1,';')", "      NaN;"},
403ea7e50cdSPeter Klausler               {"(EX9.1,';')", "      NaN;"},
404ffc67bb3SDavid Spickett               {"(G0,';')", "NaN;"},
405ffc67bb3SDavid Spickett           }},
406ffc67bb3SDavid Spickett       {// NaN (sign irrelevant)
407ffc67bb3SDavid Spickett           0xfff0000000000001,
408ffc67bb3SDavid Spickett           {
409ffc67bb3SDavid Spickett               {"(E9.1,';')", "      NaN;"},
410ffc67bb3SDavid Spickett               {"(F9.1,';')", "      NaN;"},
411ffc67bb3SDavid Spickett               {"(G9.1,';')", "      NaN;"},
412ffc67bb3SDavid Spickett               {"(SP,E9.1,';')", "      NaN;"},
413ffc67bb3SDavid Spickett               {"(SP,F9.1,';')", "      NaN;"},
414ffc67bb3SDavid Spickett               {"(SP,G9.1,';')", "      NaN;"},
415ea7e50cdSPeter Klausler               {"(SP,EX9.1,';')", "      NaN;"},
416ffc67bb3SDavid Spickett               {"(G0,';')", "NaN;"},
417ffc67bb3SDavid Spickett           }},
418ffc67bb3SDavid Spickett       {// 0.1 rounded
419ffc67bb3SDavid Spickett           0x3fb999999999999a,
420ffc67bb3SDavid Spickett           {
421ffc67bb3SDavid Spickett               {"(E62.55,';')",
422ffc67bb3SDavid Spickett                   " 0.1000000000000000055511151231257827021181583404541015625E+"
423ffc67bb3SDavid Spickett                   "00;"},
424033b491cSPeter Klausler               {"(E0.1,';')", ".1E+00;"},
425ffc67bb3SDavid Spickett               {"(E0.55,';')",
426ffc67bb3SDavid Spickett                   ".1000000000000000055511151231257827021181583404541015625E+"
427ffc67bb3SDavid Spickett                   "00;"},
428ffc67bb3SDavid Spickett               {"(E0,';')", ".1E+00;"},
429ffc67bb3SDavid Spickett               {"(F58.55,';')",
430ffc67bb3SDavid Spickett                   " 0."
431ffc67bb3SDavid Spickett                   "1000000000000000055511151231257827021181583404541015625;"},
432ffc67bb3SDavid Spickett               {"(F0.0,';')", "0.;"},
433ffc67bb3SDavid Spickett               {"(F0.55,';')",
434ffc67bb3SDavid Spickett                   ".1000000000000000055511151231257827021181583404541015625;"},
435ffc67bb3SDavid Spickett               {"(F0,';')", ".1;"},
436ffc67bb3SDavid Spickett               {"(G62.55,';')",
437ffc67bb3SDavid Spickett                   " 0.1000000000000000055511151231257827021181583404541015625  "
438ffc67bb3SDavid Spickett                   "  ;"},
439ffc67bb3SDavid Spickett               {"(G0.0,';')", "0.;"},
440ffc67bb3SDavid Spickett               {"(G0.55,';')",
441ffc67bb3SDavid Spickett                   ".1000000000000000055511151231257827021181583404541015625;"},
442ffc67bb3SDavid Spickett               {"(G0,';')", ".1;"},
443ea7e50cdSPeter Klausler               {"(EX20.12,';')", " 0XC.CCCCCCCCCCCDP-7;"},
444ffc67bb3SDavid Spickett           }},
445ffc67bb3SDavid Spickett       {// 1.5
446ffc67bb3SDavid Spickett           0x3ff8000000000000,
447ffc67bb3SDavid Spickett           {
448ffc67bb3SDavid Spickett               {"(E9.2,';')", " 0.15E+01;"},
449ffc67bb3SDavid Spickett               {"(F4.1,';')", " 1.5;"},
450ffc67bb3SDavid Spickett               {"(G7.1,';')", " 2.    ;"},
451ea7e50cdSPeter Klausler               {"(EX9.1,';')", " 0XC.0P-3;"},
452ffc67bb3SDavid Spickett               {"(RN,E8.1,';')", " 0.2E+01;"},
453ffc67bb3SDavid Spickett               {"(RN,F3.0,';')", " 2.;"},
454ffc67bb3SDavid Spickett               {"(RN,G7.0,';')", " 0.E+01;"},
455ffc67bb3SDavid Spickett               {"(RN,G7.1,';')", " 2.    ;"},
456ffc67bb3SDavid Spickett               {"(RD,E8.1,';')", " 0.1E+01;"},
457ffc67bb3SDavid Spickett               {"(RD,F3.0,';')", " 1.;"},
458ffc67bb3SDavid Spickett               {"(RD,G7.0,';')", " 0.E+01;"},
459ffc67bb3SDavid Spickett               {"(RD,G7.1,';')", " 1.    ;"},
460ffc67bb3SDavid Spickett               {"(RU,E8.1,';')", " 0.2E+01;"},
461ffc67bb3SDavid Spickett               {"(RU,G7.0,';')", " 0.E+01;"},
462ffc67bb3SDavid Spickett               {"(RU,G7.1,';')", " 2.    ;"},
463ffc67bb3SDavid Spickett               {"(RZ,E8.1,';')", " 0.1E+01;"},
464ffc67bb3SDavid Spickett               {"(RZ,F3.0,';')", " 1.;"},
465ffc67bb3SDavid Spickett               {"(RZ,G7.0,';')", " 0.E+01;"},
466ffc67bb3SDavid Spickett               {"(RZ,G7.1,';')", " 1.    ;"},
467ffc67bb3SDavid Spickett               {"(RC,E8.1,';')", " 0.2E+01;"},
468ffc67bb3SDavid Spickett               {"(RC,F3.0,';')", " 2.;"},
469ffc67bb3SDavid Spickett               {"(RC,G7.0,';')", " 0.E+01;"},
470ffc67bb3SDavid Spickett               {"(RC,G7.1,';')", " 2.    ;"},
471ffc67bb3SDavid Spickett           }},
472ffc67bb3SDavid Spickett       {// -1.5
473ffc67bb3SDavid Spickett           0xbff8000000000000,
474ffc67bb3SDavid Spickett           {
475ffc67bb3SDavid Spickett               {"(E9.2,';')", "-0.15E+01;"},
476ffc67bb3SDavid Spickett               {"(RN,E8.1,';')", "-0.2E+01;"},
477ffc67bb3SDavid Spickett               {"(RD,E8.1,';')", "-0.2E+01;"},
478ffc67bb3SDavid Spickett               {"(RU,E8.1,';')", "-0.1E+01;"},
479ffc67bb3SDavid Spickett               {"(RZ,E8.1,';')", "-0.1E+01;"},
480ffc67bb3SDavid Spickett               {"(RC,E8.1,';')", "-0.2E+01;"},
481ea7e50cdSPeter Klausler               {"(EX9.1,';')", "-0XC.0P-3;"},
482ffc67bb3SDavid Spickett           }},
483ffc67bb3SDavid Spickett       {// 2.5
484ffc67bb3SDavid Spickett           0x4004000000000000,
485ffc67bb3SDavid Spickett           {
486ffc67bb3SDavid Spickett               {"(E9.2,';')", " 0.25E+01;"},
487ffc67bb3SDavid Spickett               {"(RN,E8.1,';')", " 0.2E+01;"},
488ffc67bb3SDavid Spickett               {"(RD,E8.1,';')", " 0.2E+01;"},
489ffc67bb3SDavid Spickett               {"(RU,E8.1,';')", " 0.3E+01;"},
490ffc67bb3SDavid Spickett               {"(RZ,E8.1,';')", " 0.2E+01;"},
491ffc67bb3SDavid Spickett               {"(RC,E8.1,';')", " 0.3E+01;"},
492ea7e50cdSPeter Klausler               {"(EX9.1,';')", " 0XA.0P-2;"},
493ffc67bb3SDavid Spickett           }},
494ffc67bb3SDavid Spickett       {// -2.5
495ffc67bb3SDavid Spickett           0xc004000000000000,
496ffc67bb3SDavid Spickett           {
497ffc67bb3SDavid Spickett               {"(E9.2,';')", "-0.25E+01;"},
498ffc67bb3SDavid Spickett               {"(RN,E8.1,';')", "-0.2E+01;"},
499ffc67bb3SDavid Spickett               {"(RD,E8.1,';')", "-0.3E+01;"},
500ffc67bb3SDavid Spickett               {"(RU,E8.1,';')", "-0.2E+01;"},
501ffc67bb3SDavid Spickett               {"(RZ,E8.1,';')", "-0.2E+01;"},
502ffc67bb3SDavid Spickett               {"(RC,E8.1,';')", "-0.3E+01;"},
503ea7e50cdSPeter Klausler               {"(EX9.1,';')", "-0XA.0P-2;"},
504ffc67bb3SDavid Spickett           }},
505ffc67bb3SDavid Spickett       {// least positive nonzero subnormal
506ffc67bb3SDavid Spickett           1,
507ffc67bb3SDavid Spickett           {
508ffc67bb3SDavid Spickett               {"(E32.17,';')", "         0.49406564584124654-323;"},
509ffc67bb3SDavid Spickett               {"(ES32.17,';')", "         4.94065645841246544-324;"},
510ffc67bb3SDavid Spickett               {"(EN32.17,';')", "         4.94065645841246544-324;"},
511ffc67bb3SDavid Spickett               {"(E759.752,';')",
512ffc67bb3SDavid Spickett                   " 0."
513ffc67bb3SDavid Spickett                   "494065645841246544176568792868221372365059802614324764425585"
514ffc67bb3SDavid Spickett                   "682500675507270208751865299836361635992379796564695445717730"
515ffc67bb3SDavid Spickett                   "926656710355939796398774796010781878126300713190311404527845"
516ffc67bb3SDavid Spickett                   "817167848982103688718636056998730723050006387409153564984387"
517ffc67bb3SDavid Spickett                   "312473397273169615140031715385398074126238565591171026658556"
518ffc67bb3SDavid Spickett                   "686768187039560310624931945271591492455329305456544401127480"
519ffc67bb3SDavid Spickett                   "129709999541931989409080416563324524757147869014726780159355"
520ffc67bb3SDavid Spickett                   "238611550134803526493472019379026810710749170333222684475333"
521ffc67bb3SDavid Spickett                   "572083243193609238289345836806010601150616980975307834227731"
522ffc67bb3SDavid Spickett                   "832924790498252473077637592724787465608477820373446969953364"
523ffc67bb3SDavid Spickett                   "701797267771758512566055119913150489110145103786273816725095"
524ffc67bb3SDavid Spickett                   "583738973359899366480994116420570263709027924276754456522908"
525ffc67bb3SDavid Spickett                   "75386825064197182655334472656250-323;"},
526ffc67bb3SDavid Spickett               {"(G0,';')", ".5E-323;"},
527ffc67bb3SDavid Spickett               {"(E757.750,';')",
528ffc67bb3SDavid Spickett                   " 0."
529ffc67bb3SDavid Spickett                   "494065645841246544176568792868221372365059802614324764425585"
530ffc67bb3SDavid Spickett                   "682500675507270208751865299836361635992379796564695445717730"
531ffc67bb3SDavid Spickett                   "926656710355939796398774796010781878126300713190311404527845"
532ffc67bb3SDavid Spickett                   "817167848982103688718636056998730723050006387409153564984387"
533ffc67bb3SDavid Spickett                   "312473397273169615140031715385398074126238565591171026658556"
534ffc67bb3SDavid Spickett                   "686768187039560310624931945271591492455329305456544401127480"
535ffc67bb3SDavid Spickett                   "129709999541931989409080416563324524757147869014726780159355"
536ffc67bb3SDavid Spickett                   "238611550134803526493472019379026810710749170333222684475333"
537ffc67bb3SDavid Spickett                   "572083243193609238289345836806010601150616980975307834227731"
538ffc67bb3SDavid Spickett                   "832924790498252473077637592724787465608477820373446969953364"
539ffc67bb3SDavid Spickett                   "701797267771758512566055119913150489110145103786273816725095"
540ffc67bb3SDavid Spickett                   "583738973359899366480994116420570263709027924276754456522908"
541ffc67bb3SDavid Spickett                   "753868250641971826553344726562-323;"},
542ffc67bb3SDavid Spickett               {"(RN,E757.750,';')",
543ffc67bb3SDavid Spickett                   " 0."
544ffc67bb3SDavid Spickett                   "494065645841246544176568792868221372365059802614324764425585"
545ffc67bb3SDavid Spickett                   "682500675507270208751865299836361635992379796564695445717730"
546ffc67bb3SDavid Spickett                   "926656710355939796398774796010781878126300713190311404527845"
547ffc67bb3SDavid Spickett                   "817167848982103688718636056998730723050006387409153564984387"
548ffc67bb3SDavid Spickett                   "312473397273169615140031715385398074126238565591171026658556"
549ffc67bb3SDavid Spickett                   "686768187039560310624931945271591492455329305456544401127480"
550ffc67bb3SDavid Spickett                   "129709999541931989409080416563324524757147869014726780159355"
551ffc67bb3SDavid Spickett                   "238611550134803526493472019379026810710749170333222684475333"
552ffc67bb3SDavid Spickett                   "572083243193609238289345836806010601150616980975307834227731"
553ffc67bb3SDavid Spickett                   "832924790498252473077637592724787465608477820373446969953364"
554ffc67bb3SDavid Spickett                   "701797267771758512566055119913150489110145103786273816725095"
555ffc67bb3SDavid Spickett                   "583738973359899366480994116420570263709027924276754456522908"
556ffc67bb3SDavid Spickett                   "753868250641971826553344726562-323;"},
557ffc67bb3SDavid Spickett               {"(RD,E757.750,';')",
558ffc67bb3SDavid Spickett                   " 0."
559ffc67bb3SDavid Spickett                   "494065645841246544176568792868221372365059802614324764425585"
560ffc67bb3SDavid Spickett                   "682500675507270208751865299836361635992379796564695445717730"
561ffc67bb3SDavid Spickett                   "926656710355939796398774796010781878126300713190311404527845"
562ffc67bb3SDavid Spickett                   "817167848982103688718636056998730723050006387409153564984387"
563ffc67bb3SDavid Spickett                   "312473397273169615140031715385398074126238565591171026658556"
564ffc67bb3SDavid Spickett                   "686768187039560310624931945271591492455329305456544401127480"
565ffc67bb3SDavid Spickett                   "129709999541931989409080416563324524757147869014726780159355"
566ffc67bb3SDavid Spickett                   "238611550134803526493472019379026810710749170333222684475333"
567ffc67bb3SDavid Spickett                   "572083243193609238289345836806010601150616980975307834227731"
568ffc67bb3SDavid Spickett                   "832924790498252473077637592724787465608477820373446969953364"
569ffc67bb3SDavid Spickett                   "701797267771758512566055119913150489110145103786273816725095"
570ffc67bb3SDavid Spickett                   "583738973359899366480994116420570263709027924276754456522908"
571ffc67bb3SDavid Spickett                   "753868250641971826553344726562-323;"},
572ffc67bb3SDavid Spickett               {"(RU,E757.750,';')",
573ffc67bb3SDavid Spickett                   " 0."
574ffc67bb3SDavid Spickett                   "494065645841246544176568792868221372365059802614324764425585"
575ffc67bb3SDavid Spickett                   "682500675507270208751865299836361635992379796564695445717730"
576ffc67bb3SDavid Spickett                   "926656710355939796398774796010781878126300713190311404527845"
577ffc67bb3SDavid Spickett                   "817167848982103688718636056998730723050006387409153564984387"
578ffc67bb3SDavid Spickett                   "312473397273169615140031715385398074126238565591171026658556"
579ffc67bb3SDavid Spickett                   "686768187039560310624931945271591492455329305456544401127480"
580ffc67bb3SDavid Spickett                   "129709999541931989409080416563324524757147869014726780159355"
581ffc67bb3SDavid Spickett                   "238611550134803526493472019379026810710749170333222684475333"
582ffc67bb3SDavid Spickett                   "572083243193609238289345836806010601150616980975307834227731"
583ffc67bb3SDavid Spickett                   "832924790498252473077637592724787465608477820373446969953364"
584ffc67bb3SDavid Spickett                   "701797267771758512566055119913150489110145103786273816725095"
585ffc67bb3SDavid Spickett                   "583738973359899366480994116420570263709027924276754456522908"
586ffc67bb3SDavid Spickett                   "753868250641971826553344726563-323;"},
587ffc67bb3SDavid Spickett               {"(RC,E757.750,';')",
588ffc67bb3SDavid Spickett                   " 0."
589ffc67bb3SDavid Spickett                   "494065645841246544176568792868221372365059802614324764425585"
590ffc67bb3SDavid Spickett                   "682500675507270208751865299836361635992379796564695445717730"
591ffc67bb3SDavid Spickett                   "926656710355939796398774796010781878126300713190311404527845"
592ffc67bb3SDavid Spickett                   "817167848982103688718636056998730723050006387409153564984387"
593ffc67bb3SDavid Spickett                   "312473397273169615140031715385398074126238565591171026658556"
594ffc67bb3SDavid Spickett                   "686768187039560310624931945271591492455329305456544401127480"
595ffc67bb3SDavid Spickett                   "129709999541931989409080416563324524757147869014726780159355"
596ffc67bb3SDavid Spickett                   "238611550134803526493472019379026810710749170333222684475333"
597ffc67bb3SDavid Spickett                   "572083243193609238289345836806010601150616980975307834227731"
598ffc67bb3SDavid Spickett                   "832924790498252473077637592724787465608477820373446969953364"
599ffc67bb3SDavid Spickett                   "701797267771758512566055119913150489110145103786273816725095"
600ffc67bb3SDavid Spickett                   "583738973359899366480994116420570263709027924276754456522908"
601ffc67bb3SDavid Spickett                   "753868250641971826553344726563-323;"},
602ea7e50cdSPeter Klausler               {"(EX24.13,';')", " 0X8.0000000000000P-1077;"},
603ffc67bb3SDavid Spickett           }},
604ffc67bb3SDavid Spickett       {// least positive nonzero normal
605ffc67bb3SDavid Spickett           0x10000000000000,
606ffc67bb3SDavid Spickett           {
607ffc67bb3SDavid Spickett               {"(E723.716,';')",
608ffc67bb3SDavid Spickett                   " 0."
609ffc67bb3SDavid Spickett                   "222507385850720138309023271733240406421921598046233183055332"
610ffc67bb3SDavid Spickett                   "741688720443481391819585428315901251102056406733973103581100"
611ffc67bb3SDavid Spickett                   "515243416155346010885601238537771882113077799353200233047961"
612ffc67bb3SDavid Spickett                   "014744258363607192156504694250373420837525080665061665815894"
613ffc67bb3SDavid Spickett                   "872049117996859163964850063590877011830487479978088775374994"
614ffc67bb3SDavid Spickett                   "945158045160505091539985658247081864511353793580499211598108"
615ffc67bb3SDavid Spickett                   "576605199243335211435239014879569960959128889160299264151106"
616ffc67bb3SDavid Spickett                   "346631339366347758651302937176204732563178148566435087212282"
617ffc67bb3SDavid Spickett                   "863764204484681140761391147706280168985324411002416144742161"
618ffc67bb3SDavid Spickett                   "856716615054015428508471675290190316132277889672970737312333"
619ffc67bb3SDavid Spickett                   "408698898317506783884692609277397797285865965494109136909540"
620ffc67bb3SDavid Spickett                   "61364675687023986783152906809846172109246253967285156250-"
621ffc67bb3SDavid Spickett                   "307;"},
622ffc67bb3SDavid Spickett               {"(G0,';')", ".22250738585072014E-307;"},
623ea7e50cdSPeter Klausler               {"(EX24.13,';')", " 0X8.0000000000000P-1025;"},
624ffc67bb3SDavid Spickett           }},
625ffc67bb3SDavid Spickett       {// greatest finite
626ffc67bb3SDavid Spickett           0x7fefffffffffffffuLL,
627ffc67bb3SDavid Spickett           {
628ffc67bb3SDavid Spickett               {"(E32.17,';')", "         0.17976931348623157+309;"},
629ffc67bb3SDavid Spickett               {"(E317.310,';')",
630ffc67bb3SDavid Spickett                   " 0."
631ffc67bb3SDavid Spickett                   "179769313486231570814527423731704356798070567525844996598917"
632ffc67bb3SDavid Spickett                   "476803157260780028538760589558632766878171540458953514382464"
633ffc67bb3SDavid Spickett                   "234321326889464182768467546703537516986049910576551282076245"
634ffc67bb3SDavid Spickett                   "490090389328944075868508455133942304583236903222948165808559"
635ffc67bb3SDavid Spickett                   "332123348274797826204144723168738177180919299881250404026184"
636ffc67bb3SDavid Spickett                   "1248583680+309;"},
637ffc67bb3SDavid Spickett               {"(ES317.310,';')",
638ffc67bb3SDavid Spickett                   " 1."
639ffc67bb3SDavid Spickett                   "797693134862315708145274237317043567980705675258449965989174"
640ffc67bb3SDavid Spickett                   "768031572607800285387605895586327668781715404589535143824642"
641ffc67bb3SDavid Spickett                   "343213268894641827684675467035375169860499105765512820762454"
642ffc67bb3SDavid Spickett                   "900903893289440758685084551339423045832369032229481658085593"
643ffc67bb3SDavid Spickett                   "321233482747978262041447231687381771809192998812504040261841"
644ffc67bb3SDavid Spickett                   "2485836800+308;"},
645ffc67bb3SDavid Spickett               {"(EN319.310,';')",
646ffc67bb3SDavid Spickett                   " 179."
647ffc67bb3SDavid Spickett                   "769313486231570814527423731704356798070567525844996598917476"
648ffc67bb3SDavid Spickett                   "803157260780028538760589558632766878171540458953514382464234"
649ffc67bb3SDavid Spickett                   "321326889464182768467546703537516986049910576551282076245490"
650ffc67bb3SDavid Spickett                   "090389328944075868508455133942304583236903222948165808559332"
651ffc67bb3SDavid Spickett                   "123348274797826204144723168738177180919299881250404026184124"
652ffc67bb3SDavid Spickett                   "8583680000+306;"},
653ffc67bb3SDavid Spickett               {"(G0,';')", ".17976931348623157E+309;"},
654ea7e50cdSPeter Klausler               {"(EX24.13,';')", " 0XF.FFFFFFFFFFFF8P+1020;"},
655ea7e50cdSPeter Klausler           }},
656ea7e50cdSPeter Klausler       {// EX rounding
65714e221aaSPeter Klausler           0x3ff0100000000000uLL,
658ea7e50cdSPeter Klausler           {
65914e221aaSPeter Klausler               {"(F11.8,';')", " 1.00390625;"},
66014e221aaSPeter Klausler               {"(EX10.2,';')", " 0X8.08P-3;"},
66114e221aaSPeter Klausler               {"(EX10.1,';')", "  0X8.0P-3;"},
66214e221aaSPeter Klausler               {"(EX10.0,';')", " 0X8.08P-3;"},
66314e221aaSPeter Klausler               {"(EX0.0,';')", "0X8.08P-3;"},
66414e221aaSPeter Klausler               {"(EX0,';')", "0X8.08P-3;"},
66514e221aaSPeter Klausler               {"(RN,EX10.1,';')", "  0X8.0P-3;"},
66614e221aaSPeter Klausler               {"(RU,EX10.1,';')", "  0X8.1P-3;"},
66714e221aaSPeter Klausler               {"(RD,EX10.1,';')", "  0X8.0P-3;"},
66814e221aaSPeter Klausler               {"(RZ,EX10.1,';')", "  0X8.0P-3;"},
66914e221aaSPeter Klausler               {"(RC,EX10.1,';')", "  0X8.1P-3;"},
67014e221aaSPeter Klausler               {"(RN,EX10.0,';')", " 0X8.08P-3;"},
67114e221aaSPeter Klausler               {"(RU,EX10.0,';')", " 0X8.08P-3;"},
67214e221aaSPeter Klausler               {"(RD,EX10.0,';')", " 0X8.08P-3;"},
67314e221aaSPeter Klausler               {"(RZ,EX10.0,';')", " 0X8.08P-3;"},
67414e221aaSPeter Klausler               {"(RC,EX10.0,';')", " 0X8.08P-3;"},
675ea7e50cdSPeter Klausler           }},
676ea7e50cdSPeter Klausler       {// EX rounding
67714e221aaSPeter Klausler           0xbff0100000000000uLL,
678ea7e50cdSPeter Klausler           {
67914e221aaSPeter Klausler               {"(F11.8,';')", "-1.00390625;"},
68014e221aaSPeter Klausler               {"(EX10.2,';')", "-0X8.08P-3;"},
68114e221aaSPeter Klausler               {"(EX10.1,';')", " -0X8.0P-3;"},
68214e221aaSPeter Klausler               {"(EX10.0,';')", "-0X8.08P-3;"},
68314e221aaSPeter Klausler               {"(EX0.0,';')", "-0X8.08P-3;"},
68414e221aaSPeter Klausler               {"(EX0,';')", "-0X8.08P-3;"},
68514e221aaSPeter Klausler               {"(RN,EX10.1,';')", " -0X8.0P-3;"},
68614e221aaSPeter Klausler               {"(RU,EX10.1,';')", " -0X8.0P-3;"},
68714e221aaSPeter Klausler               {"(RD,EX10.1,';')", " -0X8.1P-3;"},
68814e221aaSPeter Klausler               {"(RZ,EX10.1,';')", " -0X8.0P-3;"},
68914e221aaSPeter Klausler               {"(RC,EX10.1,';')", " -0X8.1P-3;"},
69014e221aaSPeter Klausler               {"(RN,EX10.0,';')", "-0X8.08P-3;"},
69114e221aaSPeter Klausler               {"(RU,EX10.0,';')", "-0X8.08P-3;"},
69214e221aaSPeter Klausler               {"(RD,EX10.0,';')", "-0X8.08P-3;"},
69314e221aaSPeter Klausler               {"(RZ,EX10.0,';')", "-0X8.08P-3;"},
69414e221aaSPeter Klausler               {"(RC,EX10.0,';')", "-0X8.08P-3;"},
695ffc67bb3SDavid Spickett           }},
696ffc67bb3SDavid Spickett   };
697ffc67bb3SDavid Spickett 
698ffc67bb3SDavid Spickett   for (auto const &[value, cases] : testCases) {
699ffc67bb3SDavid Spickett     for (auto const &[format, expect] : cases) {
700ffc67bb3SDavid Spickett       std::string got;
701ffc67bb3SDavid Spickett       ASSERT_TRUE(CompareFormatReal(format, value, expect, got))
702ffc67bb3SDavid Spickett           << "Failed to format " << format << ", expected '" << expect
703ffc67bb3SDavid Spickett           << "', got '" << got << "'";
704ffc67bb3SDavid Spickett     }
705ffc67bb3SDavid Spickett   }
706ffc67bb3SDavid Spickett 
707ffc67bb3SDavid Spickett   using IndividualTestCaseTy = std::tuple<const char *, double, const char *>;
708ffc67bb3SDavid Spickett   static const std::vector<IndividualTestCaseTy> individualTestCases{
709ffc67bb3SDavid Spickett       {"(F5.3,';')", 25., "*****;"},
710ffc67bb3SDavid Spickett       {"(F5.3,';')", 2.5, "2.500;"},
711ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.25, "0.250;"},
712ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.025, "0.025;"},
713ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.0025, "0.003;"},
714ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.00025, "0.000;"},
715ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.000025, "0.000;"},
716ffc67bb3SDavid Spickett       {"(F5.3,';')", -25., "*****;"},
717ffc67bb3SDavid Spickett       {"(F5.3,';')", -2.5, "*****;"},
718ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.25, "-.250;"},
719ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.025, "-.025;"},
720ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.0025, "-.003;"},
721ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.00025, "-.000;"},
722ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.000025, "-.000;"},
723ffc67bb3SDavid Spickett       {"(F5.3,';')", 99.999, "*****;"},
724ffc67bb3SDavid Spickett       {"(F5.3,';')", 9.9999, "*****;"},
725ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.99999, "1.000;"},
726ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.099999, "0.100;"},
727ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.0099999, "0.010;"},
728ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.00099999, "0.001;"},
729ced631e0SPeter Klausler       {"(F5.3,';')",
730ced631e0SPeter Klausler           0.0005000000000000000104083408558608425664715468883514404296875,
731ced631e0SPeter Klausler           "0.001;"},
732ced631e0SPeter Klausler       {"(F5.3,';')",
733ced631e0SPeter Klausler           0.000499999999999999901988123607310399165726266801357269287109375,
734ced631e0SPeter Klausler           "0.000;"},
735ffc67bb3SDavid Spickett       {"(F5.3,';')", 0.000099999, "0.000;"},
736ffc67bb3SDavid Spickett       {"(F5.3,';')", -99.999, "*****;"},
737ffc67bb3SDavid Spickett       {"(F5.3,';')", -9.9999, "*****;"},
738ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.99999, "*****;"},
739ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.099999, "-.100;"},
740ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.0099999, "-.010;"},
741ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.00099999, "-.001;"},
742ced631e0SPeter Klausler       {"(F5.3,';')",
743ced631e0SPeter Klausler           -0.0005000000000000000104083408558608425664715468883514404296875,
744ced631e0SPeter Klausler           "-.001;"},
745ced631e0SPeter Klausler       {"(F5.3,';')",
746ced631e0SPeter Klausler           -0.000499999999999999901988123607310399165726266801357269287109375,
747ced631e0SPeter Klausler           "-.000;"},
748ffc67bb3SDavid Spickett       {"(F5.3,';')", -0.000099999, "-.000;"},
749ffc67bb3SDavid Spickett       {"(F0.1,';')", 0.0, ".0;"},
750ced631e0SPeter Klausler       {"(F5.0,';')", -0.5000000000000001, "  -1.;"},
751ced631e0SPeter Klausler       {"(F5.0,';')", -0.5, "  -0.;"},
752ced631e0SPeter Klausler       {"(F5.0,';')", -0.49999999999999994, "  -0.;"},
753ced631e0SPeter Klausler       {"(F5.0,';')", 0.49999999999999994, "   0.;"},
754ced631e0SPeter Klausler       {"(F5.0,';')", 0.5, "   0.;"},
755ced631e0SPeter Klausler       {"(F5.0,';')", 0.5000000000000001, "   1.;"},
756b1a1d4e0SPeter Klausler       {"(ES0.0E0,';')", 0.666, "7.E-1;"},
757b1a1d4e0SPeter Klausler       {"(EN0.0E0,';')", 0.666, "666.E-3;"},
758ffc67bb3SDavid Spickett   };
759ffc67bb3SDavid Spickett 
760ffc67bb3SDavid Spickett   for (auto const &[format, value, expect] : individualTestCases) {
761ffc67bb3SDavid Spickett     std::string got;
762ced631e0SPeter Klausler     char hex[17];
763ced631e0SPeter Klausler     std::snprintf(hex, sizeof hex, "%016llx",
764ced631e0SPeter Klausler         *reinterpret_cast<const unsigned long long *>(&value));
765ffc67bb3SDavid Spickett     ASSERT_TRUE(CompareFormatReal(format, value, expect, got))
766ced631e0SPeter Klausler         << "Failed to format " << value << " 0x" << hex << " with format "
767ced631e0SPeter Klausler         << format << ", expected '" << expect << "', got '" << got << "'";
768ffc67bb3SDavid Spickett   }
769ffc67bb3SDavid Spickett 
770ffc67bb3SDavid Spickett   // Problematic EN formatting edge cases with rounding
771ffc67bb3SDavid Spickett   using IndividualENTestCaseTy = std::tuple<std::uint64_t, const char *>;
772ffc67bb3SDavid Spickett   static const std::vector<IndividualENTestCaseTy> individualENTestCases{
773ffc67bb3SDavid Spickett       {0x3E11183197785F8C, " 995.0E-12"}, // 0.9950312500000000115852E-09
774ffc67bb3SDavid Spickett       {0x3E11180E68455D30, " 995.0E-12"}, // 0.9949999999999999761502E-09
775ffc67bb3SDavid Spickett       {0x3E112BD8F4F6B0D7, " 999.5E-12"}, // 0.9994999999999999089118E-09
776ffc67bb3SDavid Spickett       {0x3E45794883CA8782, "  10.0E-09"}, // 0.9999499999999999642266E-08
777ffc67bb3SDavid Spickett       {0x3F506218230C7482, " 999.9E-06"}, // 0.9999499999999998840761E-03
778ffc67bb3SDavid Spickett       {0x3FB99652BD3C3612, " 100.0E-03"}, // 0.9999500000000000055067E+00
779ffc67bb3SDavid Spickett       {0x4023E66666666667, "  10.0E+00"}, // 0.9950000000000001065814E+01
780ffc67bb3SDavid Spickett   };
781ffc67bb3SDavid Spickett 
782ffc67bb3SDavid Spickett   for (auto const &[value, expect] : individualENTestCases) {
783ffc67bb3SDavid Spickett     std::string got;
784ffc67bb3SDavid Spickett     ASSERT_TRUE(CompareFormatReal("(EN10.1)", value, expect, got))
785ffc67bb3SDavid Spickett         << "Failed to format EN10.1, expected '" << expect << "', got '" << got
786ffc67bb3SDavid Spickett         << "'";
787ffc67bb3SDavid Spickett   }
788ffc67bb3SDavid Spickett }
789ffc67bb3SDavid Spickett 
790ffc67bb3SDavid Spickett TEST(IOApiTests, FormatIntegerValues) {
791ffc67bb3SDavid Spickett   using IntTestCaseTy = std::tuple<const char *, std::int64_t, const char *>;
792ffc67bb3SDavid Spickett   static const std::vector<IntTestCaseTy> intTestCases{
793ffc67bb3SDavid Spickett       {"(I4)", 0, "   0"},
794ffc67bb3SDavid Spickett       {"(I4)", 1, "   1"},
795ffc67bb3SDavid Spickett       {"(I4)", 9999, "9999"},
796ffc67bb3SDavid Spickett       {"(SP,I4)", 1, "  +1"},
797ffc67bb3SDavid Spickett       {"(SP,I4)", 9999, "****"},
798ffc67bb3SDavid Spickett       {"(SP,I4)", 999, "+999"},
799ffc67bb3SDavid Spickett       {"(I4)", -1, "  -1"},
800ffc67bb3SDavid Spickett       {"(I4)", -9999, "****"},
801ffc67bb3SDavid Spickett       {"(I4)", -999, "-999"},
802ffc67bb3SDavid Spickett       {"(I4.2)", 1, "  01"},
803ffc67bb3SDavid Spickett       {"(I4.2)", -1, " -01"},
804ffc67bb3SDavid Spickett       {"(I4.2)", 999, " 999"},
805ffc67bb3SDavid Spickett       {"(I4.4)", 999, "0999"},
806ffc67bb3SDavid Spickett       {"(I0)", 0, "0"},
807ffc67bb3SDavid Spickett       {"(I0)", 1, "1"},
808ffc67bb3SDavid Spickett       {"(I0)", 9999, "9999"},
809ffc67bb3SDavid Spickett       {"(SP,I0)", 1, "+1"},
810ffc67bb3SDavid Spickett       {"(SP,I0)", 9999, "+9999"},
811ffc67bb3SDavid Spickett       {"(SP,I0)", 999, "+999"},
812ffc67bb3SDavid Spickett       {"(I0)", -1, "-1"},
813ffc67bb3SDavid Spickett       {"(I0)", -9999, "-9999"},
814ffc67bb3SDavid Spickett       {"(I0)", -999, "-999"},
815ffc67bb3SDavid Spickett       {"(I0.2)", 1, "01"},
816ffc67bb3SDavid Spickett       {"(I0.2)", -1, "-01"},
817ffc67bb3SDavid Spickett       {"(I0.2)", 999, "999"},
818ffc67bb3SDavid Spickett       {"(I0.4)", 999, "0999"},
819ffc67bb3SDavid Spickett       {"(G4)", 0, "   0"},
820ffc67bb3SDavid Spickett       {"(G4)", 1, "   1"},
821ffc67bb3SDavid Spickett       {"(G4)", 9999, "9999"},
822ffc67bb3SDavid Spickett       {"(SP,G4)", 1, "  +1"},
823ffc67bb3SDavid Spickett       {"(SP,G4)", 9999, "****"},
824ffc67bb3SDavid Spickett       {"(SP,G4)", 999, "+999"},
825ffc67bb3SDavid Spickett       {"(G4)", -1, "  -1"},
826ffc67bb3SDavid Spickett       {"(G4)", -9999, "****"},
827ffc67bb3SDavid Spickett       {"(G4)", -999, "-999"},
828ffc67bb3SDavid Spickett       {"(G4.2)", 1, "   1"},
829ffc67bb3SDavid Spickett       {"(G4.2)", -1, "  -1"},
830ffc67bb3SDavid Spickett       {"(G4.2)", 999, " 999"},
831ffc67bb3SDavid Spickett       {"(G4.4)", 999, " 999"},
832ffc67bb3SDavid Spickett       {"(G0)", 0, "0"},
833ffc67bb3SDavid Spickett       {"(G0)", 1, "1"},
834ffc67bb3SDavid Spickett       {"(G0)", 9999, "9999"},
835ffc67bb3SDavid Spickett       {"(SP,G0)", 1, "+1"},
836ffc67bb3SDavid Spickett       {"(SP,G0)", 9999, "+9999"},
837ffc67bb3SDavid Spickett       {"(SP,G0)", 999, "+999"},
838ffc67bb3SDavid Spickett       {"(G0)", -1, "-1"},
839ffc67bb3SDavid Spickett       {"(G0)", -9999, "-9999"},
840ffc67bb3SDavid Spickett       {"(G0)", -999, "-999"},
841ffc67bb3SDavid Spickett       {"(G0.2)", 1, "1"},
842ffc67bb3SDavid Spickett       {"(G0.2)", -1, "-1"},
843ffc67bb3SDavid Spickett       {"(G0.2)", 999, "999"},
844ffc67bb3SDavid Spickett       {"(G0.4)", 999, "999"},
845ffc67bb3SDavid Spickett   };
846ffc67bb3SDavid Spickett 
847ffc67bb3SDavid Spickett   for (auto const &[fmt, value, expect] : intTestCases) {
848ffc67bb3SDavid Spickett     std::string got;
849ffc67bb3SDavid Spickett     ASSERT_TRUE(CompareFormatInteger(fmt, value, expect, got))
850ffc67bb3SDavid Spickett         << "Failed to format " << fmt << ", expected '" << expect << "', got '"
851ffc67bb3SDavid Spickett         << got << "'";
852ffc67bb3SDavid Spickett   }
853ffc67bb3SDavid Spickett }
854ffc67bb3SDavid Spickett 
855ffc67bb3SDavid Spickett //------------------------------------------------------------------------------
856ea7e50cdSPeter Klausler /// Tests for input editing real values
857ffc67bb3SDavid Spickett //------------------------------------------------------------------------------
858ffc67bb3SDavid Spickett 
859ffc67bb3SDavid Spickett // Ensure double input values correctly map to raw uint64 values
860ea7e50cdSPeter Klausler TEST(IOApiTests, EditDoubleInputValues) {
8611346037fSPeter Klausler   using TestCaseTy = std::tuple<const char *, const char *, std::uint64_t, int>;
8621346037fSPeter Klausler   int ovf{IostatRealInputOverflow};
863ffc67bb3SDavid Spickett   static const std::vector<TestCaseTy> testCases{
8641346037fSPeter Klausler       {"(F18.0)", "                 0", 0x0, 0},
8651346037fSPeter Klausler       {"(F18.0)", "                  ", 0x0, 0},
8661346037fSPeter Klausler       {"(F18.0)", "                -0", 0x8000000000000000, 0},
8671346037fSPeter Klausler       {"(F18.0)", "                01", 0x3ff0000000000000, 0},
8681346037fSPeter Klausler       {"(F18.0)", "                 1", 0x3ff0000000000000, 0},
8691346037fSPeter Klausler       {"(F18.0)", "              125.", 0x405f400000000000, 0},
8701346037fSPeter Klausler       {"(F18.0)", "              12.5", 0x4029000000000000, 0},
8711346037fSPeter Klausler       {"(F18.0)", "              1.25", 0x3ff4000000000000, 0},
8721346037fSPeter Klausler       {"(F18.0)", "             01.25", 0x3ff4000000000000, 0},
8731346037fSPeter Klausler       {"(F18.0)", "              .125", 0x3fc0000000000000, 0},
8741346037fSPeter Klausler       {"(F18.0)", "             0.125", 0x3fc0000000000000, 0},
8751346037fSPeter Klausler       {"(F18.0)", "             .0625", 0x3fb0000000000000, 0},
8761346037fSPeter Klausler       {"(F18.0)", "            0.0625", 0x3fb0000000000000, 0},
8771346037fSPeter Klausler       {"(F18.0)", "               125", 0x405f400000000000, 0},
8781346037fSPeter Klausler       {"(F18.1)", "               125", 0x4029000000000000, 0},
8791346037fSPeter Klausler       {"(F18.2)", "               125", 0x3ff4000000000000, 0},
8801346037fSPeter Klausler       {"(F18.3)", "               125", 0x3fc0000000000000, 0},
8811346037fSPeter Klausler       {"(-1P,F18.0)", "               125", 0x4093880000000000, 0}, // 1250
8821346037fSPeter Klausler       {"(1P,F18.0)", "               125", 0x4029000000000000, 0}, // 12.5
8831346037fSPeter Klausler       {"(BZ,F18.0)", "              125 ", 0x4093880000000000, 0}, // 1250
8841346037fSPeter Klausler       {"(BZ,F18.0)", "       125 . e +1 ", 0x42a6bcc41e900000, 0}, // 1.25e13
8851346037fSPeter Klausler       {"(BZ,F18.0)", "           .      ", 0x0, 0},
8861346037fSPeter Klausler       {"(BZ,F18.0)", "           . e +1 ", 0x0, 0},
8871346037fSPeter Klausler       {"(DC,F18.0)", "              12,5", 0x4029000000000000, 0},
8881346037fSPeter Klausler       {"(EX22.0)", "0X0P0                 ", 0x0, 0}, // +0.
8891346037fSPeter Klausler       {"(EX22.0)", "-0X0P0                ", 0x8000000000000000, 0}, // -0.
8901346037fSPeter Klausler       {"(EX22.0)", "0X.8P1                ", 0x3ff0000000000000, 0}, // 1.0
8911346037fSPeter Klausler       {"(EX22.0)", "0X8.P-3               ", 0x3ff0000000000000, 0}, // 1.0
8921346037fSPeter Klausler       {"(EX22.0)", "0X.1P4                ", 0x3ff0000000000000, 0}, // 1.0
8931346037fSPeter Klausler       {"(EX22.0)", "0X10.P-4              ", 0x3ff0000000000000, 0}, // 1.0
8941346037fSPeter Klausler       {"(EX22.0)", "0X8.00P-3             ", 0x3ff0000000000000, 0}, // 1.0
8951346037fSPeter Klausler       {"(EX22.0)", "0X80.0P-6             ", 0x4000000000000000, 0}, // 2.0
8961346037fSPeter Klausler       {"(EX22.0)", "0XC.CCCCCCCCCCCDP-7   ", 0x3fb999999999999a, 0}, // 0.1
8971346037fSPeter Klausler       {"(EX22.0)", "0X.8P-1021            ", 0x0010000000000000,
8981346037fSPeter Klausler           0}, // min normal
8991346037fSPeter Klausler       {"(EX22.0)", "0X.8P-1022            ", 0x0008000000000000,
9001346037fSPeter Klausler           0}, // subnormal
9011346037fSPeter Klausler       {"(EX22.0)", "0X.8P-1073            ", 0x0000000000000001,
9021346037fSPeter Klausler           0}, // min subn.
9031346037fSPeter Klausler       {"(EX22.0)", "0X.FFFFFFFFFFFFF8P1024", 0x7fefffffffffffff,
9041346037fSPeter Klausler           0}, // max finite
9051346037fSPeter Klausler       {"(EX22.0)", "0X.8P1025             ", 0x7ff0000000000000, ovf}, // +Inf
9061346037fSPeter Klausler       {"(EX22.0)", "-0X.8P1025            ", 0xfff0000000000000, ovf}, // -Inf
9077eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X1.0000000000000P0   ", 0x3ff0000000000000, 0},
9087eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X1.00000000000008P0  ", 0x3ff0000000000001, 0},
9097eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X1.000000000000008P0 ", 0x3ff0000000000000, 0},
9107eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X1.00000000000004P0  ", 0x3ff0000000000000, 0},
9117eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X.80000000000000P1   ", 0x3ff0000000000000, 0},
9127eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X.80000000000004P1   ", 0x3ff0000000000001, 0},
9137eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X.800000000000004P1  ", 0x3ff0000000000000, 0},
9147eb5d4fcSPeter Klausler       {"(RC,EX22.0)", "0X.80000000000002P1   ", 0x3ff0000000000000, 0},
9151346037fSPeter Klausler       {"(RZ,F7.0)", " 2.e308", 0x7fefffffffffffff, 0}, // +HUGE()
9161346037fSPeter Klausler       {"(RD,F7.0)", " 2.e308", 0x7fefffffffffffff, 0}, // +HUGE()
9171346037fSPeter Klausler       {"(RU,F7.0)", " 2.e308", 0x7ff0000000000000, ovf}, // +Inf
9181346037fSPeter Klausler       {"(RZ,F7.0)", "-2.e308", 0xffefffffffffffff, 0}, // -HUGE()
9191346037fSPeter Klausler       {"(RD,F7.0)", "-2.e308", 0xfff0000000000000, ovf}, // -Inf
9201346037fSPeter Klausler       {"(RU,F7.0)", "-2.e308", 0xffefffffffffffff, 0}, // -HUGE()
9211346037fSPeter Klausler       {"(RZ,F7.0)", " 1.e999", 0x7fefffffffffffff, 0}, // +HUGE()
9221346037fSPeter Klausler       {"(RD,F7.0)", " 1.e999", 0x7fefffffffffffff, 0}, // +HUGE()
9231346037fSPeter Klausler       {"(RU,F7.0)", " 1.e999", 0x7ff0000000000000, ovf}, // +Inf
9241346037fSPeter Klausler       {"(RZ,F7.0)", "-1.e999", 0xffefffffffffffff, 0}, // -HUGE()
9251346037fSPeter Klausler       {"(RD,F7.0)", "-1.e999", 0xfff0000000000000, ovf}, // -Inf
9261346037fSPeter Klausler       {"(RU,F7.0)", "-1.e999", 0xffefffffffffffff, 0}, // -HUGE()
927f45723cdSPeter Klausler       {"(E9.1)", " 1.0E-325", 0x0, 0},
928f45723cdSPeter Klausler       {"(RU,E9.1)", " 1.0E-325", 0x1, 0},
9294762c655SPeter Klausler       {"(E9.1)", "-1.0E-325", 0x8000000000000000, 0},
930f45723cdSPeter Klausler       {"(RD,E9.1)", "-1.0E-325", 0x8000000000000001, 0},
931ffc67bb3SDavid Spickett   };
9321346037fSPeter Klausler   for (auto const &[format, data, want, iostat] : testCases) {
933ffc67bb3SDavid Spickett     auto cookie{IONAME(BeginInternalFormattedInput)(
934ffc67bb3SDavid Spickett         data, std::strlen(data), format, std::strlen(format))};
935ffc67bb3SDavid Spickett     union {
936ffc67bb3SDavid Spickett       double x;
937ffc67bb3SDavid Spickett       std::uint64_t raw;
938ffc67bb3SDavid Spickett     } u;
939ffc67bb3SDavid Spickett     u.raw = 0;
940ffc67bb3SDavid Spickett 
941ffc67bb3SDavid Spickett     // Read buffer into union value
942ffc67bb3SDavid Spickett     IONAME(EnableHandlers)(cookie, true, true, true, true, true);
943ffc67bb3SDavid Spickett     IONAME(InputReal64)(cookie, u.x);
944ffc67bb3SDavid Spickett 
945ffc67bb3SDavid Spickett     static constexpr int bufferSize{65};
946ffc67bb3SDavid Spickett     char iomsg[bufferSize];
947ffc67bb3SDavid Spickett     std::memset(iomsg, '\0', bufferSize - 1);
948ffc67bb3SDavid Spickett 
9491346037fSPeter Klausler     // Ensure no unexpected errors were encountered reading input buffer into
9501346037fSPeter Klausler     // union value
951ffc67bb3SDavid Spickett     IONAME(GetIoMsg)(cookie, iomsg, bufferSize - 1);
952ffc67bb3SDavid Spickett     auto status{IONAME(EndIoStatement)(cookie)};
9531346037fSPeter Klausler     ASSERT_EQ(status, iostat)
9541346037fSPeter Klausler         << '\'' << format << "' failed reading '" << data << "', status "
9551346037fSPeter Klausler         << static_cast<int>(status) << " != expected " << iostat << " iomsg '"
9561346037fSPeter Klausler         << iomsg << "'";
957ffc67bb3SDavid Spickett 
958ffc67bb3SDavid Spickett     // Ensure raw uint64 value matches expected conversion from double
959ffc67bb3SDavid Spickett     ASSERT_EQ(u.raw, want) << '\'' << format << "' failed reading '" << data
960ffc67bb3SDavid Spickett                            << "', want " << want << ", got " << u.raw;
961ffc67bb3SDavid Spickett   }
962ffc67bb3SDavid Spickett }
963fa465b47SPeter Klausler 
964fa465b47SPeter Klausler // regression test for confusing digit minimization
965fa465b47SPeter Klausler TEST(IOApiTests, ConfusingMinimization) {
966fa465b47SPeter Klausler   char buffer[8]{};
967fa465b47SPeter Klausler   auto cookie{IONAME(BeginInternalListOutput)(buffer, sizeof buffer)};
968fa465b47SPeter Klausler   StaticDescriptor<0> staticDescriptor;
969fa465b47SPeter Klausler   Descriptor &desc{staticDescriptor.descriptor()};
970fa465b47SPeter Klausler   std::uint16_t x{0x7bff}; // HUGE(0._2)
971fa465b47SPeter Klausler   desc.Establish(TypeCode{CFI_type_half_float}, sizeof x, &x, 0, nullptr);
972fa465b47SPeter Klausler   desc.Check();
973fa465b47SPeter Klausler   EXPECT_TRUE(IONAME(OutputDescriptor)(cookie, desc));
974fa465b47SPeter Klausler   auto status{IONAME(EndIoStatement)(cookie)};
975fa465b47SPeter Klausler   EXPECT_EQ(status, 0);
976fa465b47SPeter Klausler   std::string got{std::string{buffer, sizeof buffer}};
977fa465b47SPeter Klausler   EXPECT_TRUE(CompareFormattedStrings(" 65504. ", got))
978fa465b47SPeter Klausler       << "expected ' 65504. ', got '" << got << '\''; // not 65500.!
979fa465b47SPeter Klausler }
980