Blender V5.0
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
19
20#include "BLI_utildefines.h"
21
22#include <iosfwd>
23
24namespace blender::bits {
25
29static constexpr int64_t BitsPerInt = int64_t(sizeof(BitInt) * 8);
31static constexpr int64_t BitToIntIndexShift = 3 + (sizeof(BitInt) >= 2) + (sizeof(BitInt) >= 4) +
32 (sizeof(BitInt) >= 8);
34static constexpr BitInt BitIndexMask = (BitInt(1) << BitToIntIndexShift) - 1;
35
37{
38 BLI_assert(n >= 0);
40 if (n == BitsPerInt) {
41 return BitInt(-1);
42 }
43 return (BitInt(1) << n) - 1;
44}
45
47{
49}
50
51inline BitInt mask_range_bits(const int64_t start, const int64_t size)
52{
53 BLI_assert(start >= 0);
54 BLI_assert(size >= 0);
55 const int64_t end = start + size;
56 BLI_assert(end <= BitsPerInt);
57 if (end == BitsPerInt) {
58 return mask_last_n_bits(size);
59 }
60 return ((BitInt(1) << end) - 1) & ~((BitInt(1) << start) - 1);
61}
62
63inline BitInt mask_single_bit(const int64_t bit_index)
64{
65 BLI_assert(bit_index >= 0);
66 BLI_assert(bit_index < BitsPerInt);
67 return BitInt(1) << bit_index;
68}
69
70inline BitInt *int_containing_bit(BitInt *data, const int64_t bit_index)
71{
72 return data + (bit_index >> BitToIntIndexShift);
73}
74
75inline const BitInt *int_containing_bit(const BitInt *data, const int64_t bit_index)
76{
77 return data + (bit_index >> BitToIntIndexShift);
78}
79
84class BitRef {
85 private:
87 const BitInt *int_;
89 BitInt mask_;
90
91 friend class MutableBitRef;
92
93 public:
94 BitRef() = default;
95
100 BitRef(const BitInt *data, const int64_t bit_index)
101 {
102 int_ = int_containing_bit(data, bit_index);
103 mask_ = mask_single_bit(bit_index & BitIndexMask);
104 }
105
109 bool test() const
110 {
111 const BitInt value = *int_;
112 const BitInt masked_value = value & mask_;
113 return masked_value != 0;
114 }
115
116 operator bool() const
117 {
118 return this->test();
119 }
120};
121
126 private:
128 BitInt *int_;
130 BitInt mask_;
131
132 public:
133 MutableBitRef() = default;
134
139 MutableBitRef(BitInt *data, const int64_t bit_index)
140 {
141 int_ = int_containing_bit(data, bit_index);
142 mask_ = mask_single_bit(bit_index & BitIndexMask);
143 }
144
148 operator BitRef() const
149 {
150 BitRef bit_ref;
151 bit_ref.int_ = int_;
152 bit_ref.mask_ = mask_;
153 return bit_ref;
154 }
155
159 bool test() const
160 {
161 const BitInt value = *int_;
162 const BitInt masked_value = value & mask_;
163 return masked_value != 0;
164 }
165
166 operator bool() const
167 {
168 return this->test();
169 }
170
174 void set()
175 {
176 *int_ |= mask_;
177 }
178
182 void reset()
183 {
184 *int_ &= ~mask_;
185 }
186
191 void set(const bool value)
192 {
193 if (value) {
194 this->set();
195 }
196 else {
197 this->reset();
198 }
199 }
200
207 void set_branchless(const bool value)
208 {
209 const BitInt value_int = BitInt(value);
210 BLI_assert(ELEM(value_int, 0, 1));
211 const BitInt old = *int_;
212 *int_ =
213 /* Unset bit. */
214 (~mask_ & old)
215 /* Optionally set it again. The -1 turns a 1 into `0x00...` and a 0 into `0xff...`. */
216 | (mask_ & ~(value_int - 1));
217 }
218
219 MutableBitRef &operator|=(const bool value)
220 {
221 if (value) {
222 this->set();
223 }
224 return *this;
225 }
226
227 MutableBitRef &operator&=(const bool value)
228 {
229 if (!value) {
230 this->reset();
231 }
232 return *this;
233 }
234};
235
236std::ostream &operator<<(std::ostream &stream, const BitRef &bit);
237std::ostream &operator<<(std::ostream &stream, const MutableBitRef &bit);
238
239} // namespace blender::bits
240
241namespace blender {
242using bits::BitRef;
243using bits::MutableBitRef;
244} // namespace blender
#define BLI_assert(a)
Definition BLI_assert.h:46
#define ELEM(...)
BMesh const char void * data
long long int int64_t
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
BitRef()=default
BitRef(const BitInt *data, const int64_t bit_index)
friend class MutableBitRef
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:15
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)