1 /*===-- include/flang/Decimal/decimal.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 10 /* C and C++ API for binary-to/from-decimal conversion package. */ 11 12 #ifndef FORTRAN_DECIMAL_DECIMAL_H_ 13 #define FORTRAN_DECIMAL_DECIMAL_H_ 14 15 #include "flang/Common/api-attrs.h" 16 #include <stddef.h> 17 18 #ifdef __cplusplus 19 // Binary-to-decimal conversions (formatting) produce a sequence of decimal 20 // digit characters in a NUL-terminated user-supplied buffer that constitute 21 // a decimal fraction (or zero), accompanied by a decimal exponent that 22 // you'll get to adjust and format yourself. There can be a leading sign 23 // character. 24 // Negative zero is "-0". The result can also be "NaN", "Inf", "+Inf", 25 // or "-Inf". 26 // If the conversion can't fit in the user-supplied buffer, a null pointer 27 // is returned. 28 29 #include "binary-floating-point.h" 30 namespace Fortran::decimal { 31 #endif /* C++ */ 32 33 enum ConversionResultFlags { 34 Exact = 0, 35 Overflow = 1, 36 Inexact = 2, 37 Invalid = 4, 38 Underflow = 8, 39 }; 40 41 struct ConversionToDecimalResult { 42 const char *str; /* may not be original buffer pointer; null if overflow */ 43 size_t length; /* does not include NUL terminator */ 44 int decimalExponent; /* assuming decimal point to the left of first digit */ 45 enum ConversionResultFlags flags; 46 }; 47 48 /* The "minimize" flag causes the fewest number of output digits 49 * to be emitted such that reading them back into the same binary 50 * floating-point format with RoundNearest will return the same 51 * value. 52 */ 53 enum DecimalConversionFlags { 54 Minimize = 1, /* Minimize # of digits */ 55 AlwaysSign = 2, /* emit leading '+' if not negative */ 56 }; 57 58 /* 59 * When allocating decimal conversion output buffers, use the maximum 60 * number of significant decimal digits in the representation of the 61 * least nonzero value, and add this extra space for a sign, a NUL, and 62 * some extra due to the library working internally in base 10**16 63 * and computing its output size in multiples of 16. 64 */ 65 #define EXTRA_DECIMAL_CONVERSION_SPACE (1 + 1 + 2 * 16 - 1) 66 67 #ifdef __cplusplus 68 template <int PREC> 69 RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal(char *, size_t, 70 DecimalConversionFlags, int digits, enum FortranRounding rounding, 71 BinaryFloatingPointNumber<PREC> x); 72 73 extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<8>( 74 char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, 75 BinaryFloatingPointNumber<8>); 76 extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<11>( 77 char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, 78 BinaryFloatingPointNumber<11>); 79 extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<24>( 80 char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, 81 BinaryFloatingPointNumber<24>); 82 extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<53>( 83 char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, 84 BinaryFloatingPointNumber<53>); 85 extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<64>( 86 char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, 87 BinaryFloatingPointNumber<64>); 88 extern template RT_API_ATTRS ConversionToDecimalResult ConvertToDecimal<113>( 89 char *, size_t, enum DecimalConversionFlags, int, enum FortranRounding, 90 BinaryFloatingPointNumber<113>); 91 92 template <int PREC> struct ConversionToBinaryResult { 93 BinaryFloatingPointNumber<PREC> binary; 94 enum ConversionResultFlags flags { Exact }; 95 }; 96 97 template <int PREC> 98 RT_API_ATTRS ConversionToBinaryResult<PREC> ConvertToBinary(const char *&, 99 enum FortranRounding = RoundNearest, const char *end = nullptr); 100 101 extern template RT_API_ATTRS ConversionToBinaryResult<8> ConvertToBinary<8>( 102 const char *&, enum FortranRounding, const char *end); 103 extern template RT_API_ATTRS ConversionToBinaryResult<11> ConvertToBinary<11>( 104 const char *&, enum FortranRounding, const char *end); 105 extern template RT_API_ATTRS ConversionToBinaryResult<24> ConvertToBinary<24>( 106 const char *&, enum FortranRounding, const char *end); 107 extern template RT_API_ATTRS ConversionToBinaryResult<53> ConvertToBinary<53>( 108 const char *&, enum FortranRounding, const char *end); 109 extern template RT_API_ATTRS ConversionToBinaryResult<64> ConvertToBinary<64>( 110 const char *&, enum FortranRounding, const char *end); 111 extern template RT_API_ATTRS ConversionToBinaryResult<113> ConvertToBinary<113>( 112 const char *&, enum FortranRounding, const char *end); 113 } // namespace Fortran::decimal 114 extern "C" { 115 #define NS(x) Fortran::decimal::x 116 #else /* C++ */ 117 #define NS(x) x 118 #endif /* C++ */ 119 120 RT_API_ATTRS struct NS(ConversionToDecimalResult) 121 ConvertFloatToDecimal(char *, size_t, enum NS(DecimalConversionFlags), 122 int digits, enum NS(FortranRounding), float); 123 RT_API_ATTRS struct NS(ConversionToDecimalResult) 124 ConvertDoubleToDecimal(char *, size_t, enum NS(DecimalConversionFlags), 125 int digits, enum NS(FortranRounding), double); 126 RT_API_ATTRS struct NS(ConversionToDecimalResult) 127 ConvertLongDoubleToDecimal(char *, size_t, enum NS(DecimalConversionFlags), 128 int digits, enum NS(FortranRounding), long double); 129 130 RT_API_ATTRS enum NS(ConversionResultFlags) 131 ConvertDecimalToFloat(const char **, float *, enum NS(FortranRounding)); 132 RT_API_ATTRS enum NS(ConversionResultFlags) 133 ConvertDecimalToDouble(const char **, double *, enum NS(FortranRounding)); 134 RT_API_ATTRS enum NS(ConversionResultFlags) ConvertDecimalToLongDouble( 135 const char **, long double *, enum NS(FortranRounding)); 136 #undef NS 137 #ifdef __cplusplus 138 } // extern "C" 139 #endif 140 #endif 141