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 21 // Module ISO_C_BINDING kind C_BOOL is LOGICAL(KIND=1) and must have 22 // C's bit representation (.TRUE. -> 1, .FALSE. -> 0). 23 static constexpr bool IsLikeC{BITS <= 8 || IS_LIKE_C}; 24 Logical()25 constexpr Logical() {} // .FALSE. 26 template <int B, bool C> Logical(Logical<B,C> x)27 constexpr Logical(Logical<B, C> x) : word_{Represent(x.IsTrue())} {} Logical(bool truth)28 constexpr Logical(bool truth) : word_{Represent(truth)} {} 29 30 template <int B, bool C> constexpr Logical &operator=(Logical<B, C> x) { 31 word_ = Represent(x.IsTrue()); 32 return *this; 33 } 34 35 // Fortran actually has only .EQV. & .NEQV. relational operations 36 // for LOGICAL, but this template class supports more so that 37 // it can be used with the STL for sorting and as a key type for 38 // std::set<> & std::map<>. 39 template <int B, bool C> 40 constexpr bool operator<(const Logical<B, C> &that) const { 41 return !IsTrue() && that.IsTrue(); 42 } 43 template <int B, bool C> 44 constexpr bool operator<=(const Logical<B, C> &) const { 45 return !IsTrue(); 46 } 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> &that) const { 53 return IsTrue() != that.IsTrue(); 54 } 55 template <int B, bool C> 56 constexpr bool operator>=(const Logical<B, C> &) const { 57 return 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 IsTrue()64 constexpr bool IsTrue() const { 65 if constexpr (IsLikeC) { 66 return !word_.IsZero(); 67 } else { 68 return word_.BTEST(0); 69 } 70 } 71 NOT()72 constexpr Logical NOT() const { return {word_.IEOR(canonicalTrue)}; } 73 AND(const Logical & that)74 constexpr Logical AND(const Logical &that) const { 75 return {word_.IAND(that.word_)}; 76 } 77 OR(const Logical & that)78 constexpr Logical OR(const Logical &that) const { 79 return {word_.IOR(that.word_)}; 80 } 81 EQV(const Logical & that)82 constexpr Logical EQV(const Logical &that) const { return NEQV(that).NOT(); } 83 NEQV(const Logical & that)84 constexpr Logical NEQV(const Logical &that) const { 85 return {word_.IEOR(that.word_)}; 86 } 87 88 private: 89 using Word = Integer<bits>; 90 static constexpr Word canonicalTrue{IsLikeC ? -std::uint64_t{1} : 1}; 91 static constexpr Word canonicalFalse{0}; Represent(bool x)92 static constexpr Word Represent(bool x) { 93 return x ? canonicalTrue : canonicalFalse; 94 } Logical(const Word & w)95 constexpr Logical(const Word &w) : word_{w} {} 96 Word word_; 97 }; 98 99 extern template class Logical<8>; 100 extern template class Logical<16>; 101 extern template class Logical<32>; 102 extern template class Logical<64>; 103 } // namespace Fortran::evaluate::value 104 #endif // FORTRAN_EVALUATE_LOGICAL_H_ 105