pytorch/c10/util/Bitset.h
linhaifeng 369f2d6951 [3/N] fix typo in other folders (#166606)
fix typo in other folders

#166374
#166126

_typos.toml
```bash
[files]
extend-exclude = ["tools/linter/dictionary.txt"]
[default.extend-words]
nd = "nd"
arange = "arange"
Nd = "Nd"
GLOBALs = "GLOBALs"
hte = "hte"
iy = "iy"
PN = "PN"
Dout = "Dout"
optin = "optin"
gam = "gam"
PTD = "PTD"
Sur = "Sur"
nin = "nin"
tme = "tme"
inpt = "inpt"
mis = "mis"
Raison = "Raison"
ouput = "ouput"
nto = "nto"
Onwer = "Onwer"
callibrate = "callibrate"
ser = "ser"
Metdata = "Metdata"
```

Pull Request resolved: https://github.com/pytorch/pytorch/pull/166606
Approved by: https://github.com/ezyang
2025-10-30 10:30:40 +00:00

119 lines
3.3 KiB
C++

#pragma once
#include <cstddef>
#if defined(_MSC_VER)
#include <intrin.h>
#endif
namespace c10::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 = default;
constexpr bitset(const bitset&) noexcept = default;
constexpr bitset(bitset&&) noexcept = default;
// there is an issue 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;
~bitset() = 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>
// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
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_{0};
};
inline bool operator!=(bitset lhs, bitset rhs) noexcept {
return !(lhs == rhs);
}
} // namespace c10::utils