xref: /llvm-project/flang/include/flang/Evaluate/logical.h (revision 00e0de05723a0eee491d4a1ddad69b7fe5265805)
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