1 //===-- include/flang/Evaluate/logical.h ------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef FORTRAN_EVALUATE_LOGICAL_H_ 10 #define FORTRAN_EVALUATE_LOGICAL_H_ 11 12 #include "integer.h" 13 #include <cinttypes> 14 15 namespace Fortran::evaluate::value { 16 17 template <int BITS, bool IS_LIKE_C = true> class Logical { 18 public: 19 static constexpr int bits{BITS}; 20 using Word = Integer<bits>; 21 22 // Module ISO_C_BINDING kind C_BOOL is LOGICAL(KIND=1) and must have 23 // C's bit representation (.TRUE. -> 1, .FALSE. -> 0). 24 static constexpr bool IsLikeC{BITS <= 8 || IS_LIKE_C}; 25 Logical()26 constexpr Logical() {} // .FALSE. 27 template <int B, bool C> Logical(Logical<B,C> x)28 constexpr Logical(Logical<B, C> x) : word_{Represent(x.IsTrue())} {} Logical(bool truth)29 constexpr Logical(bool truth) : word_{Represent(truth)} {} 30 // A raw word, for DATA initialization Logical(Word && w)31 constexpr Logical(Word &&w) : word_{std::move(w)} {} 32 33 template <int B, bool C> constexpr Logical &operator=(Logical<B, C> x) { 34 word_ = Represent(x.IsTrue()); 35 return *this; 36 } 37 word()38 Word word() const { return word_; } IsCanonical()39 bool IsCanonical() const { 40 return word_ == canonicalFalse || word_ == canonicalTrue; 41 } 42 43 // Fortran actually has only .EQV. & .NEQV. relational operations 44 // for LOGICAL, but this template class supports more so that 45 // it can be used with the STL for sorting and as a key type for 46 // std::set<> & std::map<>. 47 template <int B, bool C> 48 constexpr bool operator<(const Logical<B, C> &that) const { 49 return !IsTrue() && that.IsTrue(); 50 } 51 template <int B, bool C> 52 constexpr bool operator<=(const Logical<B, C> &) const { 53 return !IsTrue(); 54 } 55 template <int B, bool C> 56 constexpr bool operator==(const Logical<B, C> &that) const { 57 return IsTrue() == that.IsTrue(); 58 } 59 template <int B, bool C> 60 constexpr bool operator!=(const Logical<B, C> &that) const { 61 return IsTrue() != that.IsTrue(); 62 } 63 template <int B, bool C> 64 constexpr bool operator>=(const Logical<B, C> &) const { 65 return IsTrue(); 66 } 67 template <int B, bool C> 68 constexpr bool operator>(const Logical<B, C> &that) const { 69 return IsTrue() && !that.IsTrue(); 70 } 71 IsTrue()72 constexpr bool IsTrue() const { 73 if constexpr (IsLikeC) { 74 return !word_.IsZero(); 75 } else { 76 return word_.BTEST(0); 77 } 78 } 79 NOT()80 constexpr Logical NOT() const { return {word_.IEOR(canonicalTrue)}; } 81 AND(const Logical & that)82 constexpr Logical AND(const Logical &that) const { 83 return {word_.IAND(that.word_)}; 84 } 85 OR(const Logical & that)86 constexpr Logical OR(const Logical &that) const { 87 return {word_.IOR(that.word_)}; 88 } 89 EQV(const Logical & that)90 constexpr Logical EQV(const Logical &that) const { return NEQV(that).NOT(); } 91 NEQV(const Logical & that)92 constexpr Logical NEQV(const Logical &that) const { 93 return {word_.IEOR(that.word_)}; 94 } 95 96 private: 97 static constexpr Word canonicalTrue{IsLikeC ? 1 : -std::uint64_t{1}}; 98 static constexpr Word canonicalFalse{0}; Represent(bool x)99 static constexpr Word Represent(bool x) { 100 return x ? canonicalTrue : canonicalFalse; 101 } 102 Word word_; 103 }; 104 105 extern template class Logical<8>; 106 extern template class Logical<16>; 107 extern template class Logical<32>; 108 extern template class Logical<64>; 109 } // namespace Fortran::evaluate::value 110 #endif // FORTRAN_EVALUATE_LOGICAL_H_ 111