Skip to content

Commit 688b973

Browse files
[libc] add options to printf decimal floats
This patch adds three options for printf decimal long doubles, and these can also apply to doubles. 1. Use a giant table which is fast and accurate, but takes up ~5MB). 2. Use dyadic floats for approximations, which only gives ~50 digits of accuracy but is very fast. 3. Use large integers for approximations, which is accurate but very slow. Reviewed By: sivachandra, lntue Differential Revision: https://reviews.llvm.org/D150399
1 parent 086183c commit 688b973

File tree

11 files changed

+872
-100
lines changed

11 files changed

+872
-100
lines changed

libc/src/__support/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ add_header_library(
102102
HDRS
103103
float_to_string.h
104104
ryu_constants.h
105+
ryu_long_double_constants.h
105106
DEPENDS
106107
.libc_assert
107108
libc.src.__support.CPP.type_traits

libc/src/__support/FPUtil/dyadic_float.h

+44-2
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,14 @@ template <size_t Bits> struct DyadicFloat {
5252
normalize();
5353
}
5454

55-
DyadicFloat(bool s, int e, MantissaType m)
55+
constexpr DyadicFloat(bool s, int e, MantissaType m)
5656
: sign(s), exponent(e), mantissa(m) {
5757
normalize();
5858
}
5959

6060
// Normalizing the mantissa, bringing the leading 1 bit to the most
6161
// significant bit.
62-
DyadicFloat &normalize() {
62+
constexpr DyadicFloat &normalize() {
6363
if (!mantissa.is_zero()) {
6464
int shift_length = static_cast<int>(mantissa.clz());
6565
exponent -= shift_length;
@@ -118,6 +118,24 @@ template <size_t Bits> struct DyadicFloat {
118118
// Still correct without FMA instructions if `d_lo` is not underflow.
119119
return multiply_add(d_lo.get_val(), T(round_and_sticky), d_hi.get_val());
120120
}
121+
122+
explicit operator MantissaType() const {
123+
if (mantissa.is_zero())
124+
return 0;
125+
126+
MantissaType new_mant = mantissa;
127+
if (exponent > 0) {
128+
new_mant <<= exponent;
129+
} else {
130+
new_mant >>= (-exponent);
131+
}
132+
133+
if (sign) {
134+
new_mant = (~new_mant) + 1;
135+
}
136+
137+
return new_mant;
138+
}
121139
};
122140

123141
// Quick add - Add 2 dyadic floats with rounding toward 0 and then normalize the
@@ -208,6 +226,30 @@ constexpr DyadicFloat<Bits> quick_mul(DyadicFloat<Bits> a,
208226
return result;
209227
}
210228

229+
// Simple exponentiation implementation for printf. Only handles positive
230+
// exponents, since division isn't implemented.
231+
template <size_t Bits>
232+
constexpr DyadicFloat<Bits> pow_n(DyadicFloat<Bits> a, uint32_t power) {
233+
DyadicFloat<Bits> result = 1.0;
234+
DyadicFloat<Bits> cur_power = a;
235+
236+
while (power > 0) {
237+
if ((power % 2) > 0) {
238+
result = quick_mul(result, cur_power);
239+
}
240+
power = power >> 1;
241+
cur_power = quick_mul(cur_power, cur_power);
242+
}
243+
return result;
244+
}
245+
246+
template <size_t Bits>
247+
constexpr DyadicFloat<Bits> mul_pow_2(DyadicFloat<Bits> a, int32_t pow_2) {
248+
DyadicFloat<Bits> result = a;
249+
result.exponent += pow_2;
250+
return result;
251+
}
252+
211253
} // namespace __llvm_libc::fputil
212254

213255
#endif // LLVM_LIBC_SRC_SUPPORT_FPUTIL_DYADIC_FLOAT_H

0 commit comments

Comments
 (0)