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