FLANG

edit-output.h
1 //===-- runtime/edit-output.h -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef FORTRAN_RUNTIME_EDIT_OUTPUT_H_
10 #define FORTRAN_RUNTIME_EDIT_OUTPUT_H_
11
12 // Output data editing templates implementing the FORMAT data editing
13 // descriptors E, EN, ES, EX, D, F, and G for REAL data (and COMPLEX
14 // components, I and G for INTEGER, and B/O/Z for both.
15 // See subclauses in 13.7.2.3 of Fortran 2018 for the
16 // detailed specifications of these descriptors.
17 // List-directed output (13.10.4) for numeric types is also done here.
18 // Drives the same fast binary-to-decimal formatting templates used
19 // in the f18 front-end.
20
21 #include "format.h"
22 #include "io-stmt.h"
23 #include "flang/Common/uint128.h"
24 #include "flang/Decimal/decimal.h"
25
26 namespace Fortran::runtime::io {
27
28 // I, B, O, Z, and G output editing for INTEGER.
29 // The DataEdit reference is const here (and elsewhere in this header) so that
30 // one edit descriptor with a repeat factor may safely serve to edit
31 // multiple elements of an array.
32 template <typename INT = std::int64_t, typename UINT = std::uint64_t>
33 bool EditIntegerOutput(IoStatementState &, const DataEdit &, INT);
34
35 // Encapsulates the state of a REAL output conversion.
36 class RealOutputEditingBase {
37 protected:
38 explicit RealOutputEditingBase(IoStatementState &io) : io_{io} {}
39
40 static bool IsInfOrNaN(const decimal::ConversionToDecimalResult &res) {
41 const char *p{res.str};
42 if (!p || res.length < 1) {
43 return false;
44 }
45 if (*p == '-' || *p == '+') {
46 if (res.length == 1) {
47 return false;
48 }
49 ++p;
50 }
51 return *p < '0' || *p > '9';
52 }
53
54 const char *FormatExponent(int, const DataEdit &edit, int &length);
55 bool EmitPrefix(const DataEdit &, std::size_t length, std::size_t width);
56 bool EmitSuffix(const DataEdit &);
57
58 IoStatementState &io_;
59 int trailingBlanks_{0}; // created when Gw editing maps to Fw
60 char exponent_[16];
61 };
62
63 template <int binaryPrecision = 53>
64 class RealOutputEditing : public RealOutputEditingBase {
65 public:
66 template <typename A>
67 RealOutputEditing(IoStatementState &io, A x)
68 : RealOutputEditingBase{io}, x_{x} {}
69 bool Edit(const DataEdit &);
70
71 private:
72 using BinaryFloatingPoint =
73 decimal::BinaryFloatingPointNumber<binaryPrecision>;
74
75 // The DataEdit arguments here are const references or copies so that
76 // the original DataEdit can safely serve multiple array elements when
77 // it has a repeat count.
78 bool EditEorDOutput(const DataEdit &);
79 bool EditFOutput(const DataEdit &);
80 DataEdit EditForGOutput(DataEdit); // returns an E or F edit
81 bool EditEXOutput(const DataEdit &);
82 bool EditListDirectedOutput(const DataEdit &);
83
84 bool IsZero() const { return x_.IsZero(); }
85
86 decimal::ConversionToDecimalResult Convert(
87 int significantDigits, const DataEdit &, int flags = 0);
88
89 BinaryFloatingPoint x_;
90 char buffer_[BinaryFloatingPoint::maxDecimalConversionDigits +
91 EXTRA_DECIMAL_CONVERSION_SPACE];
92 };
93
94 bool ListDirectedLogicalOutput(
95 IoStatementState &, ListDirectedStatementState<Direction::Output> &, bool);
96 bool EditLogicalOutput(IoStatementState &, const DataEdit &, bool);
97 bool ListDirectedDefaultCharacterOutput(IoStatementState &,
98 ListDirectedStatementState<Direction::Output> &, const char *, std::size_t);
99 bool EditDefaultCharacterOutput(
100 IoStatementState &, const DataEdit &, const char *, std::size_t);
101
102 extern template bool EditIntegerOutput<std::int64_t, std::uint64_t>(
103 IoStatementState &, const DataEdit &, std::int64_t);
104 extern template bool EditIntegerOutput<common::uint128_t, common::uint128_t>(
105 IoStatementState &, const DataEdit &, common::uint128_t);
106
107 extern template class RealOutputEditing<8>;
108 extern template class RealOutputEditing<11>;
109 extern template class RealOutputEditing<24>;
110 extern template class RealOutputEditing<53>;
111 extern template class RealOutputEditing<64>;
112 extern template class RealOutputEditing<113>;
113
114 } // namespace Fortran::runtime::io
115 #endif // FORTRAN_RUNTIME_EDIT_OUTPUT_H_
Fortran::runtime::io::ListDirectedStatementState< Direction::Output >
Definition: io-stmt.h:123
Fortran::runtime::io::IoStatementState
Definition: io-stmt.h:42
Fortran::decimal::BinaryFloatingPointNumber
Definition: binary-floating-point.h:25
Fortran::runtime::io::RealOutputEditingBase
Definition: edit-output.h:36
Fortran::runtime::io::DataEdit
Definition: format.h:40
Fortran::runtime::io::RealOutputEditing
Definition: edit-output.h:64
Fortran::common::UnsignedInt128
Definition: uint128.h:28