44ba30ae6e174ee69ac49550a408feeb4d891a27
[platform/upstream/llvm.git] / flang / include / flang / Evaluate / logical.h
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
25   constexpr Logical() {} // .FALSE.
26   template <int B, bool C>
27   constexpr Logical(Logical<B, C> x) : word_{Represent(x.IsTrue())} {}
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   }
33
34   // Fortran actually has only .EQV. & .NEQV. relational operations
35   // for LOGICAL, but this template class supports more so that
36   // it can be used with the STL for sorting and as a key type for
37   // std::set<> & std::map<>.
38   template <int B, bool C>
39   constexpr bool operator<(const Logical<B, C> &that) const {
40     return !IsTrue() && that.IsTrue();
41   }
42   template <int B, bool C>
43   constexpr bool operator<=(const Logical<B, C> &) const {
44     return !IsTrue();
45   }
46   template <int B, bool C>
47   constexpr bool operator==(const Logical<B, C> &that) const {
48     return IsTrue() == that.IsTrue();
49   }
50   template <int B, bool C>
51   constexpr bool operator!=(const Logical<B, C> &that) const {
52     return IsTrue() != that.IsTrue();
53   }
54   template <int B, bool C>
55   constexpr bool operator>=(const Logical<B, C> &) const {
56     return IsTrue();
57   }
58   template <int B, bool C>
59   constexpr bool operator>(const Logical<B, C> &that) const {
60     return IsTrue() && !that.IsTrue();
61   }
62
63   constexpr bool IsTrue() const {
64     if constexpr (IsLikeC) {
65       return !word_.IsZero();
66     } else {
67       return word_.BTEST(0);
68     }
69   }
70
71   constexpr Logical NOT() const { return {word_.IEOR(canonicalTrue)}; }
72
73   constexpr Logical AND(const Logical &that) const {
74     return {word_.IAND(that.word_)};
75   }
76
77   constexpr Logical OR(const Logical &that) const {
78     return {word_.IOR(that.word_)};
79   }
80
81   constexpr Logical EQV(const Logical &that) const { return NEQV(that).NOT(); }
82
83   constexpr Logical NEQV(const Logical &that) const {
84     return {word_.IEOR(that.word_)};
85   }
86
87 private:
88   using Word = Integer<bits>;
89   static constexpr Word canonicalTrue{IsLikeC ? -std::uint64_t{1} : 1};
90   static constexpr Word canonicalFalse{0};
91   static constexpr Word Represent(bool x) {
92     return x ? canonicalTrue : canonicalFalse;
93   }
94   constexpr Logical(const Word &w) : word_{w} {}
95   Word word_;
96 };
97
98 extern template class Logical<8>;
99 extern template class Logical<16>;
100 extern template class Logical<32>;
101 extern template class Logical<64>;
102 } // namespace Fortran::evaluate::value
103 #endif // FORTRAN_EVALUATE_LOGICAL_H_