1 //===-- include/flang/Evaluate/logical.h ------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef FORTRAN_EVALUATE_LOGICAL_H_
10 #define FORTRAN_EVALUATE_LOGICAL_H_
15 namespace Fortran::evaluate::value {
17 template <int BITS, bool IS_LIKE_C = true> class Logical {
19 static constexpr int bits{BITS};
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};
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)} {}
30 template <int B, bool C> constexpr Logical &operator=(Logical<B, C> x) {
31 word_ = Represent(x.IsTrue());
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();
42 template <int B, bool C>
43 constexpr bool operator<=(const Logical<B, C> &) const {
46 template <int B, bool C>
47 constexpr bool operator==(const Logical<B, C> &that) const {
48 return IsTrue() == that.IsTrue();
50 template <int B, bool C>
51 constexpr bool operator!=(const Logical<B, C> &that) const {
52 return IsTrue() != that.IsTrue();
54 template <int B, bool C>
55 constexpr bool operator>=(const Logical<B, C> &) const {
58 template <int B, bool C>
59 constexpr bool operator>(const Logical<B, C> &that) const {
60 return IsTrue() && !that.IsTrue();
63 constexpr bool IsTrue() const {
64 if constexpr (IsLikeC) {
65 return !word_.IsZero();
67 return word_.BTEST(0);
71 constexpr Logical NOT() const { return {word_.IEOR(canonicalTrue)}; }
73 constexpr Logical AND(const Logical &that) const {
74 return {word_.IAND(that.word_)};
77 constexpr Logical OR(const Logical &that) const {
78 return {word_.IOR(that.word_)};
81 constexpr Logical EQV(const Logical &that) const { return NEQV(that).NOT(); }
83 constexpr Logical NEQV(const Logical &that) const {
84 return {word_.IEOR(that.word_)};
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;
94 constexpr Logical(const Word &w) : word_{w} {}
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_