[flang] Reading numbers from strings.
authorpeter klausler <pklausler@nvidia.com>
Fri, 1 Jun 2018 19:37:23 +0000 (12:37 -0700)
committerpeter klausler <pklausler@nvidia.com>
Thu, 14 Jun 2018 20:52:35 +0000 (13:52 -0700)
Original-commit: flang-compiler/f18@8cbadfe7778a400756bc34dcbb5fe39334a742f8
Reviewed-on: https://github.com/flang-compiler/f18/pull/101
Tree-same-pre-rewrite: false

flang/lib/evaluate/integer.h
flang/test/evaluate/CMakeLists.txt
flang/test/evaluate/bit-population-count.cc [moved from flang/test/evaluate/bit-population-count-test.cc with 100% similarity]
flang/test/evaluate/integer.cc [moved from flang/test/evaluate/integer-test.cc with 94% similarity]
flang/test/evaluate/leading-zero-bit-count.cc [moved from flang/test/evaluate/leading-zero-bit-count-test.cc with 100% similarity]

index df5053c..13cfcbc 100644 (file)
@@ -77,6 +77,25 @@ private:
   static constexpr Part topPartMask{static_cast<Part>(~0) >> extraTopPartBits};
 
 public:
+  struct ValueWithOverflow {
+    Integer value;
+    bool overflow;
+  };
+
+  struct ValueWithCarry {
+    Integer value;
+    bool carry;
+  };
+
+  struct Product {
+    Integer upper, lower;
+  };
+
+  struct QuotientWithRemainder {
+    Integer quotient, remainder;
+    bool divisionByZero, overflow;
+  };
+
   // Constructors and value-generating static functions
   constexpr Integer() { Clear(); }  // default constructor: zero
   constexpr Integer(const Integer &) = default;
@@ -140,6 +159,39 @@ public:
     }
   }
 
+  static constexpr ValueWithOverflow ReadUnsigned(
+      const char *&pp, std::uint64_t base = 10) {
+    Integer result;
+    bool overflow{false};
+    const char *p{pp};
+    while (*p == ' ' || *p == '\t') {
+      ++p;
+    }
+    if (*p == '+') {
+      ++p;
+    }
+    Integer radix{base};
+    for (; unsigned char ch = *p; ++p) {
+      std::uint64_t digit;
+      if (ch >= '0' && ch < '0' + base) {
+        digit = ch - '0';
+      } else if (base > 10 && ch >= 'A' && ch < 'A' + base - 10) {
+        digit = ch - 'A' + 10;
+      } else if (base > 10 && ch >= 'a' && ch < 'a' + base - 10) {
+        digit = ch - 'a' + 10;
+      } else {
+        break;
+      }
+      Product shifted{result.MultiplyUnsigned(radix)};
+      overflow |= !shifted.upper.IsZero();
+      ValueWithCarry next{shifted.lower.AddUnsigned(Integer{digit})};
+      overflow |= next.carry;
+      result = next.value;
+    }
+    pp = p;
+    return {result, overflow};
+  }
+
   static constexpr Integer HUGE() { return MASKR(bits - 1); }
 
   // Returns the number of full decimal digits that can be represented.
@@ -287,10 +339,6 @@ public:
   // Two's-complement negation (-x = ~x + 1).
   // An overflow flag accompanies the result, and will be true when the
   // operand is the most negative signed number (MASKL(1)).
-  struct ValueWithOverflow {
-    Integer value;
-    bool overflow;
-  };
   constexpr ValueWithOverflow Negate() const {
     Integer result{nullptr};
     Part carry{1};
@@ -531,10 +579,6 @@ public:
   }
 
   // Unsigned addition with carry.
-  struct ValueWithCarry {
-    Integer value;
-    bool carry;
-  };
   constexpr ValueWithCarry AddUnsigned(
       const Integer &y, bool carryIn = false) const {
     Integer sum{nullptr};
@@ -587,9 +631,6 @@ public:
     }
   }
 
-  struct Product {
-    Integer upper, lower;
-  };
   constexpr Product MultiplyUnsigned(const Integer &y) const {
     Part product[2 * parts]{};  // little-endian full product
     for (int j{0}; j < parts; ++j) {
@@ -645,10 +686,6 @@ public:
     return product;
   }
 
-  struct QuotientWithRemainder {
-    Integer quotient, remainder;
-    bool divisionByZero, overflow;
-  };
   constexpr QuotientWithRemainder DivideUnsigned(const Integer &divisor) const {
     if (divisor.IsZero()) {
       return {MASKR(bits), Integer{}, true, false};  // overflow to max value
index f6fbbb3..4009641 100644 (file)
@@ -17,7 +17,7 @@ add_library(FortranEvaluateTesting
 )
 
 add_executable(leading-zero-bit-count-test
-  leading-zero-bit-count-test.cc
+  leading-zero-bit-count.cc
 )
 
 target_link_libraries(leading-zero-bit-count-test
@@ -26,7 +26,7 @@ target_link_libraries(leading-zero-bit-count-test
 )
 
 add_executable(bit-population-count-test
-  bit-population-count-test.cc
+  bit-population-count.cc
 )
 
 target_link_libraries(bit-population-count-test
@@ -35,7 +35,7 @@ target_link_libraries(bit-population-count-test
 )
 
 add_executable(integer-test
-  integer-test.cc
+  integer.cc
 )
 
 target_link_libraries(integer-test
similarity index 100%
rename from flang/test/evaluate/bit-population-count-test.cc
rename to flang/test/evaluate/bit-population-count.cc
index 21dc433..1498812 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "testing.h"
 #include "../../lib/evaluate/bit-population-count.h"
+#include "testing.h"
 
 using Fortran::evaluate::BitPopulationCount;
 using Fortran::evaluate::Parity;
similarity index 94%
rename from flang/test/evaluate/integer-test.cc
rename to flang/test/evaluate/integer.cc
index db4ca7d..d10ea80 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "testing.h"
 #include "../../lib/evaluate/integer.h"
+#include "testing.h"
 #include <cstdio>
 
 using Fortran::evaluate::Integer;
@@ -36,6 +36,7 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
   MATCH(0, zero.ToInt64())(desc);
 
   for (std::uint64_t x{0}; x <= maxUnsignedValue; ++x) {
+    unsigned long long ullx = x;
     INT a{x};
     MATCH(x, a.ToUInt64())(desc);
     INT copy{a};
@@ -43,6 +44,19 @@ template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
     copy = a;
     MATCH(x, copy.ToUInt64())(desc);
     MATCH(x == 0, a.IsZero())("%s, x=0x%llx", desc, x);
+    char buffer[64];
+    std::snprintf(buffer, sizeof buffer, "   %llu", ullx);
+    const char *p{buffer};
+    auto readcheck{INT::ReadUnsigned(p)};
+    TEST(!readcheck.overflow)("%s, x=0x%llx", desc, x);
+    MATCH(x, readcheck.value.ToUInt64())("%s, x=0x%llx", desc, x);
+    TEST(!*p)("%s, x=0x%llx", desc, x);
+    std::snprintf(buffer, sizeof buffer, "%llx", ullx);
+    p = buffer;
+    readcheck = INT::ReadUnsigned(p, 16);
+    TEST(!readcheck.overflow)("%s, x=0x%llx", desc, x);
+    MATCH(x, readcheck.value.ToUInt64())("%s, x=0x%llx", desc, x);
+    TEST(!*p)("%s, x=0x%llx", desc, x);
     INT t{a.NOT()};
     MATCH(x ^ maxUnsignedValue, t.ToUInt64())("%s, x=0x%llx", desc, x);
     auto negated{a.Negate()};
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "testing.h"
 #include "../../lib/evaluate/leading-zero-bit-count.h"
+#include "testing.h"
 
 using Fortran::evaluate::LeadingZeroBitCount;