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 BitSet(Word b)31 constexpr BitSet(Word b) : bits_{b} {} 32 33 public: BitSet()34 constexpr BitSet() {} BitSet(const std::initializer_list<int> & xs)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 size()93 static constexpr std::size_t size() { return BITS; } test(std::size_t x)94 constexpr bool test(std::size_t x) const { 95 return x < BITS && ((bits_ >> x) & 1) != 0; 96 } 97 all()98 constexpr bool all() const { return bits_ == allBits; } any()99 constexpr bool any() const { return bits_ != 0; } none()100 constexpr bool none() const { return bits_ == 0; } 101 count()102 constexpr std::size_t count() const { return BitPopulationCount(bits_); } 103 set()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 } reset()116 constexpr BitSet &reset() { 117 bits_ = 0; 118 return *this; 119 } reset(std::size_t x)120 constexpr BitSet &reset(std::size_t x) { 121 bits_ &= ~(static_cast<Word>(1) << x); 122 return *this; 123 } flip()124 constexpr BitSet &flip() { 125 bits_ ^= allBits; 126 return *this; 127 } flip(std::size_t x)128 constexpr BitSet &flip(std::size_t x) { 129 bits_ ^= static_cast<Word>(1) << x; 130 return *this; 131 } 132 LeastElement()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 bits()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_ 148