• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
RealOutputEditingBase(IoStatementState & io)38   explicit RealOutputEditingBase(IoStatementState &io) : io_{io} {}
39 
IsInfOrNaN(const decimal::ConversionToDecimalResult & res)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 KIND> class RealOutputEditing : public RealOutputEditingBase {
64 public:
65   static constexpr int binaryPrecision{common::PrecisionOfRealKind(KIND)};
66   using BinaryFloatingPoint =
67       decimal::BinaryFloatingPointNumber<binaryPrecision>;
68   template <typename A>
RealOutputEditing(IoStatementState & io,A x)69   RealOutputEditing(IoStatementState &io, A x)
70       : RealOutputEditingBase{io}, x_{x} {}
71   bool Edit(const DataEdit &);
72 
73 private:
74   // The DataEdit arguments here are const references or copies so that
75   // the original DataEdit can safely serve multiple array elements when
76   // it has a repeat count.
77   bool EditEorDOutput(const DataEdit &);
78   bool EditFOutput(const DataEdit &);
79   DataEdit EditForGOutput(DataEdit); // returns an E or F edit
80   bool EditEXOutput(const DataEdit &);
81   bool EditListDirectedOutput(const DataEdit &);
82 
IsZero()83   bool IsZero() const { return x_.IsZero(); }
84 
85   decimal::ConversionToDecimalResult Convert(
86       int significantDigits, const DataEdit &, int flags = 0);
87 
88   BinaryFloatingPoint x_;
89   char buffer_[BinaryFloatingPoint::maxDecimalConversionDigits +
90       EXTRA_DECIMAL_CONVERSION_SPACE];
91 };
92 
93 bool ListDirectedLogicalOutput(
94     IoStatementState &, ListDirectedStatementState<Direction::Output> &, bool);
95 bool EditLogicalOutput(IoStatementState &, const DataEdit &, bool);
96 bool ListDirectedDefaultCharacterOutput(IoStatementState &,
97     ListDirectedStatementState<Direction::Output> &, const char *, std::size_t);
98 bool EditDefaultCharacterOutput(
99     IoStatementState &, const DataEdit &, const char *, std::size_t);
100 
101 extern template bool EditIntegerOutput<std::int64_t, std::uint64_t>(
102     IoStatementState &, const DataEdit &, std::int64_t);
103 extern template bool EditIntegerOutput<common::uint128_t, common::uint128_t>(
104     IoStatementState &, const DataEdit &, common::uint128_t);
105 
106 extern template class RealOutputEditing<2>;
107 extern template class RealOutputEditing<3>;
108 extern template class RealOutputEditing<4>;
109 extern template class RealOutputEditing<8>;
110 extern template class RealOutputEditing<10>;
111 // TODO: double/double
112 extern template class RealOutputEditing<16>;
113 
114 } // namespace Fortran::runtime::io
115 #endif // FORTRAN_RUNTIME_EDIT_OUTPUT_H_
116