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 §ion{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(§ion.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