[flang] LOGICAL
authorpeter klausler <pklausler@nvidia.com>
Tue, 12 Jun 2018 20:33:08 +0000 (13:33 -0700)
committerpeter klausler <pklausler@nvidia.com>
Thu, 14 Jun 2018 20:52:59 +0000 (13:52 -0700)
Original-commit: flang-compiler/f18@6ec49f6edc3fc2bc4475bd08b4d3f2769b6fc441
Reviewed-on: https://github.com/flang-compiler/f18/pull/101
Tree-same-pre-rewrite: false

flang/CMakeLists.txt
flang/lib/evaluate/logical.h
flang/lib/evaluate/real.h
flang/lib/evaluate/type.h
flang/test/evaluate/CMakeLists.txt
flang/test/evaluate/integer.cc
flang/test/evaluate/logical.cc [new file with mode: 0644]

index 22556ff..b2909a5 100644 (file)
@@ -108,4 +108,5 @@ enable_testing()
 add_test(NAME Leadz COMMAND leading-zero-bit-count-test)
 add_test(NAME PopPar COMMAND bit-population-count-test)
 add_test(NAME Integer COMMAND integer-test)
+add_test(NAME Logical COMMAND logical-test)
 add_test(NAME Real COMMAND real-test)
index 6d0e583..bb62658 100644 (file)
@@ -29,9 +29,7 @@ public:
   // For static expression evaluation, all the bits will have the same value.
   constexpr bool IsTrue() const { return word_.BTEST(0); }
 
-  constexpr Logical NOT() const {
-    return {word_.NOT()};
-  }
+  constexpr Logical NOT() const { return {word_.NOT()}; }
 
   constexpr Logical AND(const Logical &that) const {
     return {word_.IAND(that.word_)};
@@ -41,9 +39,7 @@ public:
     return {word_.IOR(that.word_)};
   }
 
-  constexpr Logical EQV(const Logical &that) const {
-    return NEQV(that).NOT();
-  }
+  constexpr Logical EQV(const Logical &that) const { return NEQV(that).NOT(); }
 
   constexpr Logical NEQV(const Logical &that) const {
     return {word_.IEOR(that.word_)};
index 9c7cf80..c4c6307 100644 (file)
@@ -115,8 +115,7 @@ public:
     return result;
   }
 
-  template<typename INT>
-  constexpr INT EXPONENT() const {
+  template<typename INT> constexpr INT EXPONENT() const {
     std::uint64_t exponent{Exponent()};
     if (exponent == maxExponent) {
       return INT::HUGE();
@@ -171,7 +170,8 @@ public:
         if (lshift + precision >= result.value.bits) {
           result.flags.set(RealFlag::Overflow);
         } else {
-          result.value = result.value.ConvertUnsigned(fraction).value.SHIFTL(lshift);
+          result.value =
+              result.value.ConvertUnsigned(fraction).value.SHIFTL(lshift);
         }
       }
       if (result.flags.test(RealFlag::Overflow)) {
@@ -680,21 +680,11 @@ private:
   Word word_{};  // an Integer<>
 };
 
-using RealKind2 = Real<Integer<16>, 11>;
 extern template class Real<Integer<16>, 11>;
-
-using RealKind4 = Real<Integer<32>, 24>;
 extern template class Real<Integer<32>, 24>;
-
-using RealKind8 = Real<Integer<64>, 53>;
 extern template class Real<Integer<64>, 53>;
-
-using RealKind10 = Real<Integer<80>, 64, false>;  // 80387 extended precision
-extern template class Real<Integer<80>, 64, false>;
-
-using RealKind16 = Real<Integer<128>, 112>;
+extern template class Real<Integer<80>, 64, false>;  // 80387 extended precision
 extern template class Real<Integer<128>, 112>;
-
 // N.B. No "double-double" support.
 
 }  // namespace Fortran::evaluate::value
index 1eba656..a590d01 100644 (file)
@@ -34,11 +34,36 @@ template<int KIND> struct Integer {
   using ValueType = value::Integer<8 * kind>;
 };
 
-template<int KIND> struct Real {
+template<int KIND> struct Real;
+template<> struct Real<2> {
   static constexpr Classification classification{Classification::Real};
-  static constexpr int kind{KIND};
+  static constexpr int kind{2};
+  static constexpr bool hasLen{false};
+  using ValueType = value::Real<value::Integer<16>, 11>;
+};
+template<> struct Real<4> {
+  static constexpr Classification classification{Classification::Real};
+  static constexpr int kind{4};
   static constexpr bool hasLen{false};
-  using ValueType = value::Real<8 * K>;
+  using ValueType = value::Real<value::Integer<32>, 24>;
+};
+template<> struct Real<8> {
+  static constexpr Classification classification{Classification::Real};
+  static constexpr int kind{8};
+  static constexpr bool hasLen{false};
+  using ValueType = value::Real<value::Integer<64>, 53>;
+};
+template<> struct Real<10> {
+  static constexpr Classification classification{Classification::Real};
+  static constexpr int kind{10};
+  static constexpr bool hasLen{false};
+  using ValueType = value::Real<value::Integer<80>, 64, false>;
+};
+template<> struct Real<16> {
+  static constexpr Classification classification{Classification::Real};
+  static constexpr int kind{16};
+  static constexpr bool hasLen{false};
+  using ValueType = value::Real<value::Integer<128>, 112>;
 };
 
 #if 0  // TODO
@@ -46,7 +71,7 @@ template<int KIND> struct Complex {
   static constexpr Classification classification{Classification::Complex};
   static constexpr int kind{KIND};
   static constexpr bool hasLen{false};
-  using ValueType = value::Complex<8 * K>;
+  using ValueType = value::Complex<8 * kind>;
 };
 #endif
 
@@ -54,7 +79,7 @@ template<int KIND> struct Logical {
   static constexpr Classification classification{Classification::Logical};
   static constexpr int kind{KIND};
   static constexpr bool hasLen{false};
-  using ValueType = value::Logical<8 * K>;
+  using ValueType = value::Logical<8 * kind>;
 };
 
 #if 0  // TODO
@@ -62,7 +87,7 @@ template<int KIND> struct Character {
   static constexpr Classification classification{Classification::Character};
   static constexpr int kind{KIND};
   static constexpr bool hasLen{true};
-  using ValueType = value::Character<8 * K>;
+  using ValueType = value::Character<8 * kind>;
 };
 #endif
 
@@ -75,13 +100,13 @@ template<int KIND> struct Character {
 using DefaultReal = Real<4>;
 using DefaultInteger = Integer<DefaultReal::kind>;
 using IntrinsicTypeParameterType = DefaultInteger;
-#if 0 // TODO
+#if 0  // TODO
 using DefaultComplex = Complex<2 * DefaultReal::kind>;
 #endif
 using DefaultLogical = Logical<DefaultReal::kind>;
-#if 0 // TODO
+#if 0  // TODO
 using DefaultCharacter = Character<1>;
 #endif
 
-}  // namespace Fortran::evaluate
+}  // namespace Fortran::evaluate::type
 #endif  // FORTRAN_EVALUATE_TYPE_H_
index 92a8f96..9ee4c08 100644 (file)
@@ -44,6 +44,15 @@ target_link_libraries(integer-test
   FortranEvaluateTesting
 )
 
+add_executable(logical-test
+  logical.cc
+)
+
+target_link_libraries(logical-test
+  FortranEvaluate
+  FortranEvaluateTesting
+)
+
 add_executable(real-test
   real.cc
 )
index 6de978d..5c1082a 100644 (file)
@@ -16,8 +16,8 @@
 #include "testing.h"
 #include <cstdio>
 
-using Fortran::evaluate::value::Integer;
 using Fortran::evaluate::Ordering;
+using Fortran::evaluate::value::Integer;
 
 template<int BITS, typename INT = Integer<BITS>> void exhaustiveTesting() {
   std::uint64_t maxUnsignedValue{(std::uint64_t{1} << BITS) - 1};
diff --git a/flang/test/evaluate/logical.cc b/flang/test/evaluate/logical.cc
new file mode 100644 (file)
index 0000000..926e7ca
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (c) 2018, NVIDIA CORPORATION.  All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "testing.h"
+#include "../../lib/evaluate/type.h"
+#include <cstdio>
+
+using namespace Fortran::evaluate::type;
+
+template<int KIND> void testKind() {
+  using Type = Logical<KIND>;
+  TEST(Type::classification == Classification::Logical);
+  TEST(Type::kind == KIND);
+  TEST(!Type::hasLen);
+  using Value = typename Type::ValueType;
+  MATCH(8 * KIND, Value::bits);
+  TEST(!Value{}.IsTrue());
+  TEST(!Value{false}.IsTrue());
+  TEST(Value{true}.IsTrue());
+  TEST(Value{false}.NOT().IsTrue());
+  TEST(!Value{true}.NOT().IsTrue());
+  TEST(!Value{false}.AND(Value{false}).IsTrue());
+  TEST(!Value{false}.AND(Value{true}).IsTrue());
+  TEST(!Value{true}.AND(Value{false}).IsTrue());
+  TEST(Value{true}.AND(Value{true}).IsTrue());
+  TEST(!Value{false}.OR(Value{false}).IsTrue());
+  TEST(Value{false}.OR(Value{true}).IsTrue());
+  TEST(Value{true}.OR(Value{false}).IsTrue());
+  TEST(Value{true}.OR(Value{true}).IsTrue());
+  TEST(Value{false}.EQV(Value{false}).IsTrue());
+  TEST(!Value{false}.EQV(Value{true}).IsTrue());
+  TEST(!Value{true}.EQV(Value{false}).IsTrue());
+  TEST(Value{true}.EQV(Value{true}).IsTrue());
+  TEST(!Value{false}.NEQV(Value{false}).IsTrue());
+  TEST(Value{false}.NEQV(Value{true}).IsTrue());
+  TEST(Value{true}.NEQV(Value{false}).IsTrue());
+  TEST(!Value{true}.NEQV(Value{true}).IsTrue());
+}
+
+int main() {
+  testKind<1>();
+  testKind<2>();
+  testKind<4>();
+  testKind<8>();
+  testKind<16>();
+  return testing::Complete();
+}