mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-26 09:49:48 +00:00
[flang] Fix F5.3 formatting of 0.025
Fix F output editing in the Fortran runtime so that it respects the 'd' count of digits after the decimal mark. Reviewed By: tskeith Differential Revision: https://reviews.llvm.org/D82242
This commit is contained in:
parent
670455c77d
commit
0df6f8fe8e
@ -205,7 +205,7 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
|
||||
while (true) {
|
||||
decimal::ConversionToDecimalResult converted{
|
||||
Convert(significantDigits, edit, flags)};
|
||||
if (converted.length > 0 && !IsDecimalNumber(converted.str)) { // Inf, NaN
|
||||
if (IsInfOrNaN(converted)) {
|
||||
return EmitPrefix(edit, converted.length, editWidth) &&
|
||||
io_.Emit(converted.str, converted.length) && EmitSuffix(edit);
|
||||
}
|
||||
@ -260,8 +260,7 @@ bool RealOutputEditing<binaryPrecision>::EditEorDOutput(const DataEdit &edit) {
|
||||
template <int binaryPrecision>
|
||||
bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
|
||||
int fracDigits{edit.digits.value_or(0)}; // 'd' field
|
||||
int extraDigits{0};
|
||||
int editWidth{edit.width.value_or(0)}; // 'w' field
|
||||
const int editWidth{edit.width.value_or(0)}; // 'w' field
|
||||
int flags{0};
|
||||
if (editWidth == 0) { // "the processor selects the field width"
|
||||
if (!edit.digits.has_value()) { // F0
|
||||
@ -271,27 +270,31 @@ bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
|
||||
}
|
||||
// Multiple conversions may be needed to get the right number of
|
||||
// effective rounded fractional digits.
|
||||
int extraDigits{0};
|
||||
while (true) {
|
||||
decimal::ConversionToDecimalResult converted{
|
||||
Convert(extraDigits + fracDigits, edit, flags)};
|
||||
if (converted.length > 0 && !IsDecimalNumber(converted.str)) { // Inf, NaN
|
||||
if (IsInfOrNaN(converted)) {
|
||||
return EmitPrefix(edit, converted.length, editWidth) &&
|
||||
io_.Emit(converted.str, converted.length) && EmitSuffix(edit);
|
||||
}
|
||||
int scale{IsZero() ? -1 : edit.modes.scale};
|
||||
int expo{converted.decimalExponent - scale};
|
||||
if (expo > extraDigits) {
|
||||
if (expo > extraDigits && extraDigits >= 0) {
|
||||
extraDigits = expo;
|
||||
if (flags & decimal::Minimize) {
|
||||
if (!edit.digits.has_value()) { // F0
|
||||
fracDigits = sizeof buffer_ - extraDigits - 2; // sign & NUL
|
||||
}
|
||||
continue; // try again
|
||||
continue;
|
||||
} else if (expo < extraDigits && extraDigits > -fracDigits) {
|
||||
extraDigits = std::max(expo, -fracDigits);
|
||||
continue;
|
||||
}
|
||||
int signLength{*converted.str == '-' || *converted.str == '+' ? 1 : 0};
|
||||
int convertedDigits{static_cast<int>(converted.length) - signLength};
|
||||
int digitsBeforePoint{std::max(0, std::min(expo, convertedDigits))};
|
||||
int zeroesBeforePoint{std::max(0, expo - digitsBeforePoint)};
|
||||
int zeroesAfterPoint{std::max(0, -expo)};
|
||||
int zeroesAfterPoint{std::min(fracDigits, std::max(0, -expo))};
|
||||
int digitsAfterPoint{convertedDigits - digitsBeforePoint};
|
||||
int trailingZeroes{flags & decimal::Minimize
|
||||
? 0
|
||||
@ -299,7 +302,7 @@ bool RealOutputEditing<binaryPrecision>::EditFOutput(const DataEdit &edit) {
|
||||
if (digitsBeforePoint + zeroesBeforePoint + zeroesAfterPoint +
|
||||
digitsAfterPoint + trailingZeroes ==
|
||||
0) {
|
||||
++zeroesBeforePoint; // "." -> "0."
|
||||
zeroesBeforePoint = 1; // "." -> "0."
|
||||
}
|
||||
int totalLength{signLength + digitsBeforePoint + zeroesBeforePoint +
|
||||
1 /*'.'*/ + zeroesAfterPoint + digitsAfterPoint + trailingZeroes};
|
||||
@ -332,7 +335,7 @@ DataEdit RealOutputEditing<binaryPrecision>::EditForGOutput(DataEdit edit) {
|
||||
return edit; // Gw.0 -> Ew.0 for w > 0
|
||||
}
|
||||
decimal::ConversionToDecimalResult converted{Convert(1, edit)};
|
||||
if (!IsDecimalNumber(converted.str)) { // Inf, NaN
|
||||
if (IsInfOrNaN(converted)) {
|
||||
return edit;
|
||||
}
|
||||
int expo{IsZero() ? 1 : converted.decimalExponent}; // 's'
|
||||
@ -361,7 +364,7 @@ template <int binaryPrecision>
|
||||
bool RealOutputEditing<binaryPrecision>::EditListDirectedOutput(
|
||||
const DataEdit &edit) {
|
||||
decimal::ConversionToDecimalResult converted{Convert(1, edit)};
|
||||
if (!IsDecimalNumber(converted.str)) { // Inf, NaN
|
||||
if (IsInfOrNaN(converted)) {
|
||||
return EditEorDOutput(edit);
|
||||
}
|
||||
int expo{converted.decimalExponent};
|
||||
|
@ -37,14 +37,18 @@ class RealOutputEditingBase {
|
||||
protected:
|
||||
explicit RealOutputEditingBase(IoStatementState &io) : io_{io} {}
|
||||
|
||||
static bool IsDecimalNumber(const char *p) {
|
||||
if (!p) {
|
||||
static bool IsInfOrNaN(const decimal::ConversionToDecimalResult &res) {
|
||||
const char *p{res.str};
|
||||
if (!p || res.length < 1) {
|
||||
return false;
|
||||
}
|
||||
if (*p == '-' || *p == '+') {
|
||||
if (res.length == 1) {
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return *p >= '0' && *p <= '9';
|
||||
return *p < '0' || *p > '9';
|
||||
}
|
||||
|
||||
const char *FormatExponent(int, const DataEdit &edit, int &length);
|
||||
|
@ -402,6 +402,21 @@ int main() {
|
||||
"4040261841248583680000+306;");
|
||||
realTest("(G0,';')", u.d, ".17976931348623157+309;");
|
||||
|
||||
realTest("(F5.3,';')", 25., "*****;");
|
||||
realTest("(F5.3,';')", 2.5, "2.500;");
|
||||
realTest("(F5.3,';')", 0.25, "0.250;");
|
||||
realTest("(F5.3,';')", 0.025, "0.025;");
|
||||
realTest("(F5.3,';')", 0.0025, "0.003;");
|
||||
realTest("(F5.3,';')", 0.00025, "0.000;");
|
||||
realTest("(F5.3,';')", 0.000025, "0.000;");
|
||||
realTest("(F5.3,';')", -25., "*****;");
|
||||
realTest("(F5.3,';')", -2.5, "*****;");
|
||||
realTest("(F5.3,';')", -0.25, "-.250;");
|
||||
realTest("(F5.3,';')", -0.025, "-.025;");
|
||||
realTest("(F5.3,';')", -0.0025, "-.003;");
|
||||
realTest("(F5.3,';')", -0.00025, "-.000;");
|
||||
realTest("(F5.3,';')", -0.000025, "-.000;");
|
||||
|
||||
realInTest("(F18.0)", " 0", 0x0);
|
||||
realInTest("(F18.0)", " ", 0x0);
|
||||
realInTest("(F18.0)", " -0", 0x8000000000000000);
|
||||
|
Loading…
Reference in New Issue
Block a user