File: Bitset.h

package info (click to toggle)
pytorch 1.13.1%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 139,252 kB
  • sloc: cpp: 1,100,274; python: 706,454; ansic: 83,052; asm: 7,618; java: 3,273; sh: 2,841; javascript: 612; makefile: 323; xml: 269; ruby: 185; yacc: 144; objc: 68; lex: 44
file content (120 lines) | stat: -rw-r--r-- 3,437 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#pragma once

#include <c10/macros/Macros.h>
#include <c10/util/C++17.h>
#include <c10/util/Optional.h>
#if defined(_MSC_VER)
#include <intrin.h>
#endif

namespace c10 {
namespace utils {

/**
 * This is a simple bitset class with sizeof(long long int) bits.
 * You can set bits, unset bits, query bits by index,
 * and query for the first set bit.
 * Before using this class, please also take a look at std::bitset,
 * which has more functionality and is more generic. It is probably
 * a better fit for your use case. The sole reason for c10::utils::bitset
 * to exist is that std::bitset misses a find_first_set() method.
 */
struct bitset final {
 private:
#if defined(_MSC_VER)
  // MSVCs _BitScanForward64 expects int64_t
  using bitset_type = int64_t;
#else
  // POSIX ffsll expects long long int
  using bitset_type = long long int;
#endif
 public:
  static constexpr size_t NUM_BITS() {
    return 8 * sizeof(bitset_type);
  }

  constexpr bitset() noexcept : bitset_(0) {}
  constexpr bitset(const bitset&) noexcept = default;
  constexpr bitset(bitset&&) noexcept = default;
  // there is an issure for gcc 5.3.0 when define default function as constexpr
  // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68754.
  bitset& operator=(const bitset&) noexcept = default;
  bitset& operator=(bitset&&) noexcept = default;

  constexpr void set(size_t index) noexcept {
    bitset_ |= (static_cast<long long int>(1) << index);
  }

  constexpr void unset(size_t index) noexcept {
    bitset_ &= ~(static_cast<long long int>(1) << index);
  }

  constexpr bool get(size_t index) const noexcept {
    return bitset_ & (static_cast<long long int>(1) << index);
  }

  constexpr bool is_entirely_unset() const noexcept {
    return 0 == bitset_;
  }

  // Call the given functor with the index of each bit that is set
  template <class Func>
  void for_each_set_bit(Func&& func) const {
    bitset cur = *this;
    size_t index = cur.find_first_set();
    while (0 != index) {
      // -1 because find_first_set() is not one-indexed.
      index -= 1;
      func(index);
      cur.unset(index);
      index = cur.find_first_set();
    }
  }

 private:
  // Return the index of the first set bit. The returned index is one-indexed
  // (i.e. if the very first bit is set, this function returns '1'), and a
  // return of '0' means that there was no bit set.
  size_t find_first_set() const {
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64))
    unsigned long result;
    bool has_bits_set = (0 != _BitScanForward64(&result, bitset_));
    if (!has_bits_set) {
      return 0;
    }
    return result + 1;
#elif defined(_MSC_VER) && defined(_M_IX86)
    unsigned long result;
    if (static_cast<uint32_t>(bitset_) != 0) {
      bool has_bits_set =
          (0 != _BitScanForward(&result, static_cast<uint32_t>(bitset_)));
      if (!has_bits_set) {
        return 0;
      }
      return result + 1;
    } else {
      bool has_bits_set =
          (0 != _BitScanForward(&result, static_cast<uint32_t>(bitset_ >> 32)));
      if (!has_bits_set) {
        return 32;
      }
      return result + 33;
    }
#else
    return __builtin_ffsll(bitset_);
#endif
  }

  friend bool operator==(bitset lhs, bitset rhs) noexcept {
    return lhs.bitset_ == rhs.bitset_;
  }

  bitset_type bitset_;
};

inline bool operator!=(bitset lhs, bitset rhs) noexcept {
  return !(lhs == rhs);
}

} // namespace utils
} // namespace c10