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