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