Blender V4.3
BLI_bit_ref.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
20#include "BLI_index_range.hh"
21#include "BLI_utildefines.h"
22
23#include <iosfwd>
24
25namespace blender::bits {
26
30static constexpr int64_t BitsPerInt = int64_t(sizeof(BitInt) * 8);
32static constexpr int64_t BitToIntIndexShift = 3 + (sizeof(BitInt) >= 2) + (sizeof(BitInt) >= 4) +
33 (sizeof(BitInt) >= 8);
35static constexpr BitInt BitIndexMask = (BitInt(1) << BitToIntIndexShift) - 1;
36
38{
39 BLI_assert(n >= 0);
41 if (n == BitsPerInt) {
42 return BitInt(-1);
43 }
44 return (BitInt(1) << n) - 1;
45}
46
48{
49 return ~mask_first_n_bits(BitsPerInt - n);
50}
51
52inline BitInt mask_range_bits(const int64_t start, const int64_t size)
53{
54 BLI_assert(start >= 0);
55 BLI_assert(size >= 0);
56 const int64_t end = start + size;
57 BLI_assert(end <= BitsPerInt);
58 if (end == BitsPerInt) {
59 return mask_last_n_bits(size);
60 }
61 return ((BitInt(1) << end) - 1) & ~((BitInt(1) << start) - 1);
62}
63
64inline BitInt mask_single_bit(const int64_t bit_index)
65{
66 BLI_assert(bit_index >= 0);
67 BLI_assert(bit_index < BitsPerInt);
68 return BitInt(1) << bit_index;
69}
70
71inline BitInt *int_containing_bit(BitInt *data, const int64_t bit_index)
72{
73 return data + (bit_index >> BitToIntIndexShift);
74}
75
76inline const BitInt *int_containing_bit(const BitInt *data, const int64_t bit_index)
77{
78 return data + (bit_index >> BitToIntIndexShift);
79}
80
85class BitRef {
86 private:
88 const BitInt *int_;
90 BitInt mask_;
91
92 friend class MutableBitRef;
93
94 public:
95 BitRef() = default;
96
101 BitRef(const BitInt *data, const int64_t bit_index)
102 {
103 int_ = int_containing_bit(data, bit_index);
104 mask_ = mask_single_bit(bit_index & BitIndexMask);
105 }
106
110 bool test() const
111 {
112 const BitInt value = *int_;
113 const BitInt masked_value = value & mask_;
114 return masked_value != 0;
115 }
116
117 operator bool() const
118 {
119 return this->test();
120 }
121};
122
127 private:
129 BitInt *int_;
131 BitInt mask_;
132
133 public:
134 MutableBitRef() = default;
135
140 MutableBitRef(BitInt *data, const int64_t bit_index)
141 {
142 int_ = int_containing_bit(data, bit_index);
143 mask_ = mask_single_bit(bit_index & BitIndexMask);
144 }
145
149 operator BitRef() const
150 {
151 BitRef bit_ref;
152 bit_ref.int_ = int_;
153 bit_ref.mask_ = mask_;
154 return bit_ref;
155 }
156
160 bool test() const
161 {
162 const BitInt value = *int_;
163 const BitInt masked_value = value & mask_;
164 return masked_value != 0;
165 }
166
167 operator bool() const
168 {
169 return this->test();
170 }
171
175 void set()
176 {
177 *int_ |= mask_;
178 }
179
183 void reset()
184 {
185 *int_ &= ~mask_;
186 }
187
192 void set(const bool value)
193 {
194 if (value) {
195 this->set();
196 }
197 else {
198 this->reset();
199 }
200 }
201
208 void set_branchless(const bool value)
209 {
210 const BitInt value_int = BitInt(value);
211 BLI_assert(ELEM(value_int, 0, 1));
212 const BitInt old = *int_;
213 *int_ =
214 /* Unset bit. */
215 (~mask_ & old)
216 /* Optionally set it again. The -1 turns a 1 into `0x00...` and a 0 into `0xff...`. */
217 | (mask_ & ~(value_int - 1));
218 }
219
220 MutableBitRef &operator|=(const bool value)
221 {
222 if (value) {
223 this->set();
224 }
225 return *this;
226 }
227
228 MutableBitRef &operator&=(const bool value)
229 {
230 if (!value) {
231 this->reset();
232 }
233 return *this;
234 }
235};
236
237std::ostream &operator<<(std::ostream &stream, const BitRef &bit);
238std::ostream &operator<<(std::ostream &stream, const MutableBitRef &bit);
239
240} // namespace blender::bits
241
242namespace blender {
243using bits::BitRef;
244using bits::MutableBitRef;
245} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:50
#define ELEM(...)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
BitRef(const BitInt *data, const int64_t bit_index)
MutableBitRef(BitInt *data, const int64_t bit_index)
MutableBitRef & operator|=(const bool value)
void set(const bool value)
void set_branchless(const bool value)
MutableBitRef & operator&=(const bool value)
uint64_t BitInt
static constexpr BitInt BitIndexMask
static constexpr int64_t BitsPerInt
BitInt * int_containing_bit(BitInt *data, const int64_t bit_index)
static constexpr int64_t BitToIntIndexShift
BitInt mask_single_bit(const int64_t bit_index)
std::ostream & operator<<(std::ostream &stream, const BitRef &bit)
Definition bit_ref.cc:11
BitInt mask_last_n_bits(const int64_t n)
BitInt mask_first_n_bits(const int64_t n)
BitInt mask_range_bits(const int64_t start, const int64_t size)
__int64 int64_t
Definition stdint.h:89
unsigned __int64 uint64_t
Definition stdint.h:90