[llvm-commits] [PATCH] Add an APFloat::convertToInt(APSInt) function (issue4738043)

jyasskin at gmail.com jyasskin at gmail.com
Thu Jul 14 17:05:44 PDT 2011


Reviewers: llvm-commits_cs.uiuc.edu,

Message:
Initial diff at
http://codereview.appspot.com/download/issue4738043_1.diff.

Description:
Add an APFloat::convertToInt(APSInt) function that automatically manages
the memory for the result.

Used in http://codereview.appspot.com/4728042.

Please review this at http://codereview.appspot.com/4738043/

Affected files:
   M include/llvm/ADT/APFloat.h
   M lib/Support/APFloat.cpp
   M unittests/ADT/APFloatTest.cpp


Index: include/llvm/ADT/APFloat.h
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h
index  
21b8c86d1d5b644ced60fb47727e7a79d1106f24..d2566a44bac9cfc1940fa25fa92bf6693a4773bb  
100644
--- a/include/llvm/ADT/APFloat.h
+++ b/include/llvm/ADT/APFloat.h
@@ -109,6 +109,7 @@ namespace llvm {
    typedef signed short exponent_t;

    struct fltSemantics;
+  class APSInt;
    class StringRef;

    /* When bits of a floating point number are truncated, this enum is
@@ -283,6 +284,7 @@ namespace llvm {
      opStatus convert(const fltSemantics &, roundingMode, bool *);
      opStatus convertToInteger(integerPart *, unsigned int, bool,
                                roundingMode, bool *) const;
+    opStatus convertToInteger(APSInt&, roundingMode, bool *) const;
      opStatus convertFromAPInt(const APInt &,
                                bool, roundingMode);
      opStatus convertFromSignExtendedInteger(const integerPart *, unsigned  
int,
Index: lib/Support/APFloat.cpp
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index  
c3169acabbc7b115375c4548fadd24b4e18d00af..434fd15d1acb207aed38c57a61e04d32586fd69b  
100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -13,6 +13,7 @@
   
//===----------------------------------------------------------------------===//

  #include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
  #include "llvm/ADT/StringRef.h"
  #include "llvm/ADT/FoldingSet.h"
  #include "llvm/Support/ErrorHandling.h"
@@ -2084,6 +2085,23 @@ APFloat::convertToInteger(integerPart *parts,  
unsigned int width,
    return fs;
  }

+/* Same as convertToInteger(integerPart*, ...), except the result is  
returned in
+   an APSInt, whose initial bit-width and signed-ness are used to  
determine the
+   precision of the conversion.
+ */
+APFloat::opStatus
+APFloat::convertToInteger(APSInt &result,
+                          roundingMode rounding_mode, bool *isExact) const
+{
+  const unsigned bitWidth = result.getBitWidth();
+  SmallVector<uint64_t, 4> parts(result.getNumWords());
+  const opStatus status = convertToInteger(
+    parts.data(), bitWidth, result.isSigned(), rounding_mode, isExact);
+  // Keeps the original signed-ness.
+  result = APInt(bitWidth, parts.size(), parts.data());
+  return status;
+}
+
  /* Convert an unsigned integer SRC to a floating point number,
     rounding according to ROUNDING_MODE.  The sign of the floating
     point number is not modified.  */
Index: unittests/ADT/APFloatTest.cpp
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp
index  
5f05b861693326e3fb3513d48423d033e919ff7e..08ac2a05254a54fcc1077104ae6645288426d20c  
100644
--- a/unittests/ADT/APFloatTest.cpp
+++ b/unittests/ADT/APFloatTest.cpp
@@ -12,6 +12,7 @@
  #include "llvm/Support/raw_ostream.h"
  #include "gtest/gtest.h"
  #include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
  #include "llvm/ADT/SmallString.h"
  #include "llvm/ADT/SmallVector.h"

@@ -344,6 +345,54 @@ TEST(APFloatTest, toString) {
    ASSERT_EQ("8.731834E+2", convertToString(873.1834, 0, 0));
  }

+TEST(APFloatTest, toInteger) {
+  bool isExact = false;
+  APSInt result(5, /*isUnsigned=*/true);
+
+  EXPECT_EQ(APFloat::opOK,
+            APFloat(APFloat::IEEEdouble, "10")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_TRUE(isExact);
+  EXPECT_EQ(APSInt(APInt(5, 10), true), result);
+
+  EXPECT_EQ(APFloat::opInvalidOp,
+            APFloat(APFloat::IEEEdouble, "-10")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_FALSE(isExact);
+  EXPECT_EQ(APSInt::getMinValue(5, true), result);
+
+  EXPECT_EQ(APFloat::opInvalidOp,
+            APFloat(APFloat::IEEEdouble, "32")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_FALSE(isExact);
+  EXPECT_EQ(APSInt::getMaxValue(5, true), result);
+
+  EXPECT_EQ(APFloat::opInexact,
+            APFloat(APFloat::IEEEdouble, "7.9")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_FALSE(isExact);
+  EXPECT_EQ(APSInt(APInt(5, 7), true), result);
+
+  result.setIsUnsigned(false);
+  EXPECT_EQ(APFloat::opOK,
+            APFloat(APFloat::IEEEdouble, "-10")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_TRUE(isExact);
+  EXPECT_EQ(APSInt(APInt(5, -10, true), false), result);
+
+  EXPECT_EQ(APFloat::opInvalidOp,
+            APFloat(APFloat::IEEEdouble, "-17")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_FALSE(isExact);
+  EXPECT_EQ(APSInt::getMinValue(5, false), result);
+
+  EXPECT_EQ(APFloat::opInvalidOp,
+            APFloat(APFloat::IEEEdouble, "16")
+            .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+  EXPECT_FALSE(isExact);
+  EXPECT_EQ(APSInt::getMaxValue(5, false), result);
+}
+
  static APInt nanbits(const fltSemantics &Sem,
                       bool SNaN, bool Negative, uint64_t fill) {
    APInt apfill(64, fill);





More information about the llvm-commits mailing list