FLANG

constexpr-bitset.h
1 //===-- include/flang/Common/constexpr-bitset.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_COMMON_CONSTEXPR_BITSET_H_
10 #define FORTRAN_COMMON_CONSTEXPR_BITSET_H_
11
12 // Implements a replacement for std::bitset<> that is suitable for use
13 // in constexpr expressions. Limited to elements in [0..63].
14
15 #include "bit-population-count.h"
16 #include <cstddef>
17 #include <cstdint>
18 #include <initializer_list>
19 #include <optional>
20 #include <type_traits>
21
22 namespace Fortran::common {
23
24 template <int BITS> class BitSet {
25 static_assert(BITS > 0 && BITS <= 64);
26 static constexpr bool partialWord{BITS != 32 && BITS != 64};
27 using Word = std::conditional_t<(BITS > 32), std::uint64_t, std::uint32_t>;
28 static constexpr Word allBits{
29 partialWord ? (static_cast<Word>(1) << BITS) - 1 : ~static_cast<Word>(0)};
30
31 constexpr BitSet(Word b) : bits_{b} {}
32
33 public:
34 constexpr BitSet() {}
35 constexpr BitSet(const std::initializer_list<int> &xs) {
36 for (auto x : xs) {
37 set(x);
38 }
39 }
40 constexpr BitSet(const BitSet &) = default;
41 constexpr BitSet(BitSet &&) = default;
42 constexpr BitSet &operator=(const BitSet &) = default;
43 constexpr BitSet &operator=(BitSet &&) = default;
44
45 constexpr BitSet &operator&=(const BitSet &that) {
46 bits_ &= that.bits_;
47 return *this;
48 }
49 constexpr BitSet &operator&=(BitSet &&that) {
50 bits_ &= that.bits_;
51 return *this;
52 }
53 constexpr BitSet &operator^=(const BitSet &that) {
54 bits_ ^= that.bits_;
55 return *this;
56 }
57 constexpr BitSet &operator^=(BitSet &&that) {
58 bits_ ^= that.bits_;
59 return *this;
60 }
61 constexpr BitSet &operator|=(const BitSet &that) {
62 bits_ |= that.bits_;
63 return *this;
64 }
65 constexpr BitSet &operator|=(BitSet &&that) {
66 bits_ |= that.bits_;
67 return *this;
68 }
69
70 constexpr BitSet operator~() const { return ~bits_; }
71 constexpr BitSet operator&(const BitSet &that) const {
72 return bits_ & that.bits_;
73 }
74 constexpr BitSet operator&(BitSet &&that) const { return bits_ & that.bits_; }
75 constexpr BitSet operator^(const BitSet &that) const {
76 return bits_ ^ that.bits_;
77 }
78 constexpr BitSet operator^(BitSet &&that) const { return bits_ & that.bits_; }
79 constexpr BitSet operator|(const BitSet &that) const {
80 return bits_ | that.bits_;
81 }
82 constexpr BitSet operator|(BitSet &&that) const { return bits_ | that.bits_; }
83
84 constexpr bool operator==(const BitSet &that) const {
85 return bits_ == that.bits_;
86 }
87 constexpr bool operator==(BitSet &&that) const { return bits_ == that.bits_; }
88 constexpr bool operator!=(const BitSet &that) const {
89 return bits_ != that.bits_;
90 }
91 constexpr bool operator!=(BitSet &&that) const { return bits_ != that.bits_; }
92
93 static constexpr std::size_t size() { return BITS; }
94 constexpr bool test(std::size_t x) const {
95 return x < BITS && ((bits_ >> x) & 1) != 0;
96 }
97
98 constexpr bool all() const { return bits_ == allBits; }
99 constexpr bool any() const { return bits_ != 0; }
100 constexpr bool none() const { return bits_ == 0; }
101
102 constexpr std::size_t count() const { return BitPopulationCount(bits_); }
103
104 constexpr BitSet &set() {
105 bits_ = allBits;
106 return *this;
107 }
108 constexpr BitSet set(std::size_t x, bool value = true) {
109 if (!value) {
110 return reset(x);
111 } else {
112 bits_ |= static_cast<Word>(1) << x;
113 return *this;
114 }
115 }
116 constexpr BitSet &reset() {
117 bits_ = 0;
118 return *this;
119 }
120 constexpr BitSet &reset(std::size_t x) {
121 bits_ &= ~(static_cast<Word>(1) << x);
122 return *this;
123 }
124 constexpr BitSet &flip() {
125 bits_ ^= allBits;
126 return *this;
127 }
128 constexpr BitSet &flip(std::size_t x) {
129 bits_ ^= static_cast<Word>(1) << x;
130 return *this;
131 }
132
133 constexpr std::optional<std::size_t> LeastElement() const {
134 if (bits_ == 0) {
135 return std::nullopt;
136 } else {
137 return {TrailingZeroBitCount(bits_)};
138 }
139 }
140
141 Word bits() const { return bits_; }
142
143 private:
144 Word bits_{0};
145 };
146 } // namespace Fortran::common
147 #endif // FORTRAN_COMMON_CONSTEXPR_BITSET_H_
Fortran::common::BitSet
Definition: constexpr-bitset.h:24