[flang][runtime] Don't emit any leading blanks for G0/E0 output editing

There were cases where E0.d output editing (or G0.d editing that is converted
to E0.d) would emit one or more leading blank characters; fix them.

Differential Revision: https://reviews.llvm.org/D127426
This commit is contained in:
Peter Klausler 2022-06-08 10:42:40 -07:00
parent 17457be1c3
commit 3f3edbe5fc
2 changed files with 20 additions and 15 deletions

View File

@ -258,6 +258,7 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
if (edit.modes.editingFlags & signPlus) {
flags |= decimal::AlwaysSign;
}
bool noLeadingSpaces{editWidth == 0};
if (editWidth == 0) { // "the processor selects the field width"
if (edit.digits.has_value()) { // E0.d
if (editDigits == 0) { // E0.0
@ -360,6 +361,9 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
zeroesBeforePoint = 1;
++totalLength;
}
if (totalLength < width && noLeadingSpaces) {
width = totalLength;
}
return EmitPrefix(edit, totalLength, width) &&
io_.Emit(converted.str, signLength + digitsBeforePoint) &&
io_.EmitRepeated('0', zeroesBeforePoint) &&
@ -475,9 +479,10 @@ bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
template <int binaryPrecision>
DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
edit.descriptor = 'E';
int editWidth{edit.width.value_or(0)};
int significantDigits{
edit.digits.value_or(BinaryFloatingPoint::decimalPrecision)}; // 'd'
if (!edit.width.has_value() || (*edit.width > 0 && significantDigits == 0)) {
if (editWidth > 0 && significantDigits == 0) {
return edit; // Gw.0 -> Ew.0 for w > 0
}
int flags{0};
@ -487,7 +492,7 @@ DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
decimal::ConversionToDecimalResult converted{
Convert(significantDigits, edit.modes.round, flags)};
if (IsInfOrNaN(converted)) {
return edit;
return edit; // Inf/Nan -> Ew.d (same as Fw.d)
}
int expo{IsZero() ? 1 : converted.decimalExponent}; // 's'
if (expo < 0 || expo > significantDigits) {
@ -496,7 +501,6 @@ DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
edit.descriptor = 'F';
edit.modes.scale = 0; // kP is ignored for G when no exponent field
trailingBlanks_ = 0;
int editWidth{edit.width.value_or(0)};
if (editWidth > 0) {
int expoDigits{edit.expoDigits.value_or(0)};
trailingBlanks_ = expoDigits > 0 ? expoDigits + 2 : 4; // 'n'

View File

@ -280,8 +280,8 @@ TEST(IOApiTests, FormatZeroes) {
for (auto const &[format, expect] : zeroes) {
std::string got;
ASSERT_TRUE(CompareFormatReal(format, 0.0, expect, got))
<< "Failed to format " << format << ", expected " << expect << ", got "
<< got;
<< "Failed to format " << format << ", expected '" << expect
<< "', got '" << got << "'";
}
}
@ -311,8 +311,8 @@ TEST(IOApiTests, FormatOnes) {
for (auto const &[format, expect] : ones) {
std::string got;
ASSERT_TRUE(CompareFormatReal(format, 1.0, expect, got))
<< "Failed to format " << format << ", expected " << expect << ", got "
<< got;
<< "Failed to format " << format << ", expected '" << expect
<< "', got '" << got << "'";
}
}
@ -326,8 +326,8 @@ TEST(IOApiTests, FormatNegativeOnes) {
for (auto const &[format, expect] : negOnes) {
std::string got;
ASSERT_TRUE(CompareFormatReal(format, -1.0, expect, got))
<< "Failed to format " << format << ", expected " << expect << ", got "
<< got;
<< "Failed to format " << format << ", expected '" << expect
<< "', got '" << got << "'";
}
}
@ -394,7 +394,7 @@ TEST(IOApiTests, FormatDoubleValues) {
{"(E62.55,';')",
" 0.1000000000000000055511151231257827021181583404541015625E+"
"00;"},
{"(E0.0,';')", " 0.E+00;"},
{"(E0.0,';')", "0.E+00;"},
{"(E0.55,';')",
"0.1000000000000000055511151231257827021181583404541015625E+"
"00;"},
@ -624,8 +624,8 @@ TEST(IOApiTests, FormatDoubleValues) {
for (auto const &[format, expect] : cases) {
std::string got;
ASSERT_TRUE(CompareFormatReal(format, value, expect, got))
<< "Failed to format " << format << ", expected " << expect
<< ", got " << got;
<< "Failed to format " << format << ", expected '" << expect
<< "', got '" << got << "'";
}
}
@ -669,8 +669,8 @@ TEST(IOApiTests, FormatDoubleValues) {
for (auto const &[format, value, expect] : individualTestCases) {
std::string got;
ASSERT_TRUE(CompareFormatReal(format, value, expect, got))
<< "Failed to format " << format << ", expected " << expect << ", got "
<< got;
<< "Failed to format " << format << ", expected '" << expect
<< "', got '" << got << "'";
}
// Problematic EN formatting edge cases with rounding
@ -688,7 +688,8 @@ TEST(IOApiTests, FormatDoubleValues) {
for (auto const &[value, expect] : individualENTestCases) {
std::string got;
ASSERT_TRUE(CompareFormatReal("(EN10.1)", value, expect, got))
<< "Failed to format EN10.1, expected " << expect << ", got " << got;
<< "Failed to format EN10.1, expected '" << expect << "', got '" << got
<< "'";
}
}