[llvm] [APFloat] Add APFloat::format (PR #99088)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 8 00:28:54 PDT 2024


================
@@ -5323,6 +5399,291 @@ APFloat APFloat::getAllOnesValue(const fltSemantics &Semantics) {
   return APFloat(Semantics, APInt::getAllOnes(Semantics.sizeInBits));
 }
 
+SmallVectorImpl<char> &APFloat::format(SmallVectorImpl<char> &strout,
+                                       llvm::FloatStyle style,
+                                       std::optional<size_t> precision_in) {
+  size_t precision = precision_in.value_or(getDefaultPrecision(style));
+
+  // everything that follows assumes that precision >= 0
+  assert(precision >= 0);
+
+  // deal with the special cases
+  if (isNaN()) {
+    detail::append(strout, "nan");
+    return strout;
+  } else if (isInfinity()) {
+    if (isNegative())
+      detail::append(strout, "-INF");
+    else
+      detail::append(strout, "INF");
+    return strout;
+  } else if (isZero()) {
+    if (isNegative())
+      strout.push_back('-');
+    strout.push_back('0');
+    if (precision > 0) {
+      strout.push_back('.');
+      for (size_t i = 0; i < precision; ++i)
+        strout.push_back('0');
+    }
+    if (style == FloatStyle::Exponent)
+      detail::append(strout, "e+00");
+    else if (style == FloatStyle::ExponentUpper)
+      detail::append(strout, "E+00");
+    else if (style == FloatStyle::Percent)
+      strout.push_back('%');
+    return strout;
+  }
+
+  // check we've dealt with all the special cases
+  assert(!isNaN() && !isInfinity() && !isZero());
+
+  // get as an integer and radix 2 exponent
+  APInt I;
+  int E;
+  decomposeToIntegerAndPowerOf2(I, E);
+
+  // convert from base 2 to base 10
+  if (0 == E) {
+    // then nothing to do --- s is an integer
+  } else if (E > 0) {
+    // shift left and reduce e to 0
+    int numLeadingZeros = I.countl_zero();
+    if (E > numLeadingZeros)
+      I = I.zext(I.getBitWidth() + E - numLeadingZeros);
+    I <<= E;
+    E = 0;
+  } else {
+    // we want to convert a negative base 2 exponent
+    // to a negative base 10 exponent:
+    //   I * 2^-E   = I * 2^-E * 5^E * 5^-E
+    //              = I * 5^E * 2^-E * 5^-E
+    //              = (I * 5^E) * (2*5)^-E
+    //              = (I * 5^E) * 10^-E
+    // that is, we need to multiply I by 5^-exp and treat
+    // the exponent as being base 10
+
+    // 5^13 = 5^(8+4+1)
+    //
+    // Now work our how many bits we need for the product I * 5^E
+    // We need log2(I * 5^E)  = log2(s) + log2(5^E)
+    //                        = log2(s) + e * log2(5)
+    // log2(5) ~ 2.321928096 < 2.322033898 ~ 137/59
+    // log2(I) <= I.getBitWidth()
+
+    I = I.zext(I.getBitWidth() + (137 * -E + 136) / 59);
+    APInt power5(I.getBitWidth(), 5);
+    int exp = -E;
+    assert(exp > 0);
+    for (;;) {
+      if (exp & 1)
+        I *= power5;
+      exp >>= 1;
+      if (0 == exp)
+        break;
+      power5 *= power5;
+    }
+  }
+
+  // at this point s is an intger, and exp is either 0, or is negative
+  assert(E <= 0);
+
+  // convert s to a string
+  SmallVector<char> s;
+  I.toString(s, 10, false);
+
+  // The decimal point is at position -E (recall E is <= 0)
+  // relative to the END of the string.  If E == 0, the decimal
+  // point is to the right of the last position.
+  // Thus, if decimalPoint == s.size() + E, the decimal point is
+  // immediately to the left of s[decimalPoint].
+  // If decimalPoint is 0, the decimal point is immediately
+  // before the start of s.  If it is negative, then there are
+  // implicit zeros to the left of s.
+  int decimalPoint = s.size() + E;
+  E = 0;
+
+  if (style == FloatStyle::Exponent || style == FloatStyle::ExponentUpper) {
+    // this corresponds to printf("%e"), or [-]d[.dd..dd]e(+|-)dd
+    // We need one digit to the left of the decimal point.
+    // In other words, we need to make decimalPoint 1,
+    // and adjust E.
+    E = decimalPoint - 1;
+    decimalPoint = 1;
+
+    // now need to deal with the precision.
+    if (precision < (s.size() - 1) && (s[precision + 1] >= '5')) {
+      // then need to round.  What we do is extract the
----------------
arsenm wrote:

```suggestion
      // Then need to round.  What we do is extract the
```

Capitalize comments 

https://github.com/llvm/llvm-project/pull/99088


More information about the llvm-commits mailing list