[libc-commits] [libc] [libc] Alternative algorithm for decimal FP printf (PR #123643)
via libc-commits
libc-commits at lists.llvm.org
Wed Jan 29 06:14:38 PST 2025
================
@@ -26,6 +26,49 @@
namespace LIBC_NAMESPACE_DECL {
namespace fputil {
+// Decide whether to round a UInt up, down or not at all at a given bit
+// position, based on the current rounding mode. The assumption is that the
+// caller is going to make the integer `value >> rshift`, and then might need
+// to round it up by 1 depending on the value of the bits shifted off the
+// bottom.
+//
+// `logical_sign` causes the behavior of FE_DOWNWARD and FE_UPWARD to
+// be reversed, which is what you'd want if this is the mantissa of a
+// negative floating-point number.
+//
+// Return value is +1 if the value should be rounded up; -1 if it should be
+// rounded down; 0 if it's exact and needs no rounding.
+template <size_t Bits>
+LIBC_INLINE constexpr int
+rounding_direction(const LIBC_NAMESPACE::UInt<Bits> &value, size_t rshift,
+ Sign logical_sign) {
+ if (rshift == 0 || (rshift < Bits && (value << (Bits - rshift)) == 0) ||
+ (rshift >= Bits && value == 0))
+ return 0; // exact
+
+ switch (quick_get_round()) {
+ case FE_TONEAREST:
+ if (rshift > 0 && rshift <= Bits && value.get_bit(rshift - 1)) {
+ // We round up, unless the value is an exact halfway case and
+ // the bit that will end up in the units place is 0, in which
+ // case tie-break-to-even says round down.
+ return value.get_bit(rshift) != 0 || (value << (Bits - rshift + 1)) != 0
----------------
lntue wrote:
It looks like `value.get_bit(rshift)` will be overflow if `rshift == Bits`?
https://github.com/llvm/llvm-project/pull/123643
More information about the libc-commits
mailing list