Library for bit manipulation.
Loading...
Searching...
No Matches
bits.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 ttldtor.
2// SPDX-License-Identifier: BSL-1.0
3
4/**
5 * @file
6 * @brief Library for bit manipulation.
7 * @author ttldtor
8 */
9
10#pragma once
11
12#include <concepts>
13#include <limits>
14#include <type_traits>
15
16/**
17 * @defgroup bits Library for bit manipulation.
18 */
19/**@{*/
20
21namespace org::ttldtor::bits {
22
23namespace detail {
24template <typename T, typename...>
25struct MaxImpl {
26 using Type = T;
27};
28
29template <typename T, typename U, typename... Ts>
30struct MaxImpl<T, U, Ts...> {
31 using Type = MaxImpl<std::conditional_t<sizeof(T) >= sizeof(U), T, U>, Ts...>::Type;
32};
33} // namespace detail
34
35/**
36 * @ingroup bits
37 * Returns max type by size (first is better)
38 */
39template <typename... Ts>
40using Max = detail::MaxImpl<Ts...>::Type;
41
42/**
43 * @ingroup bits
44 * Performs a right arithmetic bit shift operation (`>>` in Java, C, etc.). The sign bit is extended to preserve the
45 * signedness of the number.
46 *
47 * The result of the shift will be of the same type as the `value` being shifted.
48 * If the shift is a negative number of bits, then a @ref ::sal() "left arithmetic shift" will be performed.
49 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then, if the `value` is
50 * negative (a signed integer type), `-1` will be returned, and if positive, then `0` will be returned.
51 *
52 * @tparam ValueType The type of `value`
53 * @tparam ShiftType The type of `shift`
54 * @param value The value to be shifted.
55 * @param shift The shift in bits
56 * @return The shifted `value`
57 */
58template <std::integral ValueType, std::integral ShiftType>
59constexpr ValueType sar(ValueType value, ShiftType shift) noexcept;
60
61/**
62 * @ingroup bits
63 * Performs a left arithmetic bit shift operation (`sal`, `<<` in Java, C, etc.). The `shift` is unsigned.
64 *
65 * The result of the shift will be of the same type as the `value` being shifted.
66 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
67 * returned.
68 *
69 * @tparam ValueType The type of `value`
70 * @tparam UnsignedShiftType The type of `shift`
71 * @param value The value to be shifted
72 * @param shift The shift in bits
73 * @return The shifted `value`
74 */
75template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
76constexpr ValueType leftArithmeticShift(ValueType value, UnsignedShiftType shift) noexcept {
77 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
78 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
79
80 if (shift < MAX_VALUE_BITS) {
81 return static_cast<ValueType>(static_cast<UnsignedValueType>(value) << shift);
82 }
83
84 return ValueType{0};
85}
86
87/**
88 * @ingroup bits
89 * Performs a left arithmetic bit shift operation (`sal`, `<<` in Java, C, etc.). The `shift` is signed.
90 *
91 * The result of the shift will be of the same type as the `value` being shifted.
92 * If the shift is a negative number of bits, then a @ref ::sar() "right arithmetic shift" will be performed.
93 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
94 * returned.
95 *
96 * @tparam ValueType The type of `value`
97 * @tparam SignedShiftType The type of `shift`
98 * @param value The value to be shifted
99 * @param shift The shift in bits
100 * @return The shifted `value`
101 */
102template <std::integral ValueType, std::signed_integral SignedShiftType>
103constexpr ValueType leftArithmeticShift(ValueType value, SignedShiftType shift) noexcept {
104 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
105
106 if (shift < 0) {
107 const UnsignedShiftType magnitude = UnsignedShiftType{0} - static_cast<UnsignedShiftType>(shift);
108
109 return sar(value, magnitude);
110 }
111
112 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
113 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
114 const auto unsignedShift = static_cast<UnsignedShiftType>(shift);
115
116 if (unsignedShift < MAX_VALUE_BITS) {
117 return static_cast<ValueType>(static_cast<UnsignedValueType>(value) << unsignedShift);
118 }
119
120 return ValueType{0};
121}
122
123/**
124 * @ingroup bits
125 * Performs a left arithmetic bit shift operation (`<<` in Java, C, etc.).
126 *
127 * The result of the shift will be of the same type as the `value` being shifted.
128 * If the shift is a negative number of bits, then a @ref ::sar() "right arithmetic shift" will be performed.
129 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
130 * returned.
131 *
132 * @tparam ValueType The type of `value`
133 * @tparam ShiftType The type of `shift`
134 * @param value The value to be shifted.
135 * @param shift The shift in bits
136 * @return The shifted `value`
137 */
138template <std::integral ValueType, std::integral ShiftType>
139constexpr ValueType sal(ValueType value, ShiftType shift) noexcept {
140 return leftArithmeticShift(value, shift);
141}
142
143/**
144 * @ingroup bits
145 * Performs a right arithmetic bit shift operation (`sar`, `>>` in Java, C, etc.). The `shift` is unsigned.
146 * The sign bit is extended to preserve the signedness of the number.
147 *
148 * The result of the shift will be of the same type as the `value` being shifted.
149 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then, if the `value` is
150 * negative (a signed integer type), `-1` will be returned, and if positive, then `0` will be returned.
151 *
152 * @tparam ValueType The type of `value`
153 * @tparam UnsignedShiftType The type of `shift`
154 * @param value The value to be shifted
155 * @param shift The shift in bits
156 * @return The shifted `value`
157 */
158template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
159constexpr ValueType rightArithmeticShift(ValueType value, UnsignedShiftType shift) noexcept {
160 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
161 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
162
163 if (shift < MAX_VALUE_BITS) {
164 return static_cast<ValueType>(value >> shift);
165 }
166
167 return value < 0 ? static_cast<ValueType>(-1) : ValueType{0};
168}
169
170/**
171 * @ingroup bits
172 * Performs a right arithmetic bit shift operation (`sar`, `>>` in Java, C, etc.). The `shift` is signed.
173 * The sign bit is extended to preserve the signedness of the number.
174 *
175 * The result of the shift will be of the same type as the `value` being shifted.
176 * If the shift is a negative number of bits, then a @ref ::sal() "left arithmetic shift" will be performed.
177 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then, if the `value` is
178 * negative (a signed integer type), `-1` will be returned, and if positive, then `0` will be returned.
179 *
180 * @tparam ValueType The type of `value`
181 * @tparam SignedShiftType The type of `shift`
182 * @param value The value to be shifted
183 * @param shift The shift in bits
184 * @return The shifted `value`
185 */
186template <std::integral ValueType, std::signed_integral SignedShiftType>
187constexpr ValueType rightArithmeticShift(ValueType value, SignedShiftType shift) noexcept {
188 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
189
190 if (shift < 0) {
191 const UnsignedShiftType magnitude = UnsignedShiftType{0} - static_cast<UnsignedShiftType>(shift);
192
193 return sal(value, magnitude);
194 }
195
196 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
197 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
198 const auto unsignedShift = static_cast<UnsignedShiftType>(shift);
199
200 if (unsignedShift < MAX_VALUE_BITS) {
201 return static_cast<ValueType>(value >> unsignedShift);
202 }
203
204 return value < 0 ? static_cast<ValueType>(-1) : ValueType{0};
205}
206
207/**
208 * @ingroup bits
209 * Performs a right arithmetic bit shift operation (`>>` in Java, C, etc.). The sign bit is extended to preserve the
210 * signedness of the number.
211 *
212 * The result of the shift will be of the same type as the `value` being shifted.
213 * If the shift is a negative number of bits, then a @ref ::sal() "left arithmetic shift" will be performed.
214 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then, if the `value` is
215 * negative (a signed integer type), `-1` will be returned, and if positive, then `0` will be returned.
216 *
217 * @tparam ValueType The type of `value`
218 * @tparam ShiftType The type of `shift`
219 * @param value The value to be shifted.
220 * @param shift The shift in bits
221 * @return The shifted `value`
222 */
223template <std::integral ValueType, std::integral ShiftType>
224constexpr ValueType sar(ValueType value, ShiftType shift) noexcept {
225 return rightArithmeticShift(value, shift);
226}
227
228/**
229 * @ingroup bits
230 * Performs a right logical bit shift operation (`>>>` in Java). Fills the left bits by zero.
231 *
232 * The result of the shift will be of the same type as the `value` being shifted.
233 * If the shift is a negative number of bits, then a @ref ::shl() "left logical shift" will be performed.
234 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
235 * returned.
236 *
237 * @tparam ValueType The type of `value`
238 * @tparam ShiftType The type of `shift`
239 * @param value The value to be shifted.
240 * @param shift The shift in bits
241 * @return The shifted `value`
242 */
243template <std::integral ValueType, std::integral ShiftType>
244constexpr ValueType shr(ValueType value, ShiftType shift) noexcept;
245
246/**
247 * @ingroup bits
248 * Performs a left logical bit shift operation (`shl`, `<<<`). The `shift` is unsigned.
249 *
250 * The result of the shift will be of the same type as the `value` being shifted.
251 * If the shift is a negative number of bits, then a @ref ::shr() "right logical shift" will be performed.
252 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
253 * returned.
254 *
255 * @tparam ValueType The type of `value`
256 * @tparam UnsignedShiftType The type of `shift`
257 * @param value The value to be shifted
258 * @param shift The shift in bits
259 * @return The shifted `value`
260 */
261template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
262constexpr ValueType leftLogicalShift(ValueType value, UnsignedShiftType shift) noexcept {
263 return leftArithmeticShift(value, shift);
264}
265
266/**
267 * @ingroup bits
268 * Performs a left logical bit shift operation (`shl`, `<<<`). The `shift` is signed.
269 *
270 * The result of the shift will be of the same type as the `value` being shifted.
271 * If the shift is a negative number of bits, then a @ref ::shr() "right logical shift" will be performed.
272 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
273 * returned.
274 *
275 * @tparam ValueType The type of `value`
276 * @tparam SignedShiftType The type of `shift`
277 * @param value The value to be shifted
278 * @param shift The shift in bits
279 * @return The shifted `value`
280 */
281template <std::integral ValueType, std::integral SignedShiftType>
282constexpr ValueType leftLogicalShift(ValueType value, SignedShiftType shift) noexcept {
283 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
284
285 if (shift < 0) {
286 const UnsignedShiftType magnitude = UnsignedShiftType{0} - static_cast<UnsignedShiftType>(shift);
287
288 return shr(value, magnitude);
289 }
290
291 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
292 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
293 const auto unsignedShift = static_cast<UnsignedShiftType>(shift);
294
295 if (unsignedShift < MAX_VALUE_BITS) {
296 return static_cast<ValueType>(static_cast<UnsignedValueType>(value) << unsignedShift);
297 }
298
299 return ValueType{0};
300}
301
302/**
303 * @ingroup bits
304 * Performs a left logical bit shift operation (`shl`, `<<<`).
305 *
306 * The result of the shift will be of the same type as the `value` being shifted.
307 * If the shift is a negative number of bits, then a @ref ::shr() "right logical shift" will be performed.
308 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
309 * returned.
310 *
311 * @tparam ValueType The type of `value`
312 * @tparam ShiftType The type of `shift`
313 * @param value The value to be shifted.
314 * @param shift The shift in bits
315 * @return The shifted `value`
316 */
317template <std::integral ValueType, std::integral ShiftType>
318constexpr ValueType shl(ValueType value, ShiftType shift) noexcept {
319 return leftLogicalShift(value, shift);
320}
321
322/**
323 * @ingroup bits
324 * Performs a right logical bit shift operation (`shr`, `>>>` in Java). The `shift` is unsigned. Fills the left bits by
325 * zero.
326 *
327 * The result of the shift will be of the same type as the `value` being shifted.
328 * If the shift is a negative number of bits, then a @ref ::shl() "left logical shift" will be performed.
329 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
330 * returned.
331 *
332 * @tparam ValueType The type of `value`
333 * @tparam UnsignedShiftType The type of `shift`
334 * @param value The value to be shifted
335 * @param shift The shift in bits
336 * @return The shifted `value`
337 */
338template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
339constexpr ValueType rightLogicalShift(ValueType value, UnsignedShiftType shift) noexcept {
340 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
341 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
342
343 if (shift < MAX_VALUE_BITS) {
344 return static_cast<ValueType>(static_cast<UnsignedValueType>(value) >> shift);
345 }
346
347 return ValueType{0};
348}
349
350/**
351 * @ingroup bits
352 * Performs a right logical bit shift operation (`shr`, `>>>` in Java). The `shift` is signed. Fills the left bits by
353 * zero.
354 *
355 * The result of the shift will be of the same type as the `value` being shifted.
356 * If the shift is a negative number of bits, then a @ref ::shl() "left logical shift" will be performed.
357 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
358 * returned.
359 *
360 * @tparam ValueType The type of `value`
361 * @tparam SignedShiftType The type of `shift`
362 * @param value The value to be shifted
363 * @param shift The shift in bits
364 * @return The shifted `value`
365 */
366template <std::integral ValueType, std::signed_integral SignedShiftType>
367constexpr ValueType rightLogicalShift(ValueType value, SignedShiftType shift) noexcept {
368 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
369
370 if (shift < 0) {
371 const UnsignedShiftType magnitude = UnsignedShiftType{0} - static_cast<UnsignedShiftType>(shift);
372
373 return shl(value, magnitude);
374 }
375
376 using UnsignedValueType = std::make_unsigned_t<std::remove_cv_t<ValueType>>;
377 constexpr auto MAX_VALUE_BITS = static_cast<UnsignedShiftType>(std::numeric_limits<UnsignedValueType>::digits);
378 const auto unsignedShift = static_cast<UnsignedShiftType>(shift);
379
380 if (unsignedShift < MAX_VALUE_BITS) {
381 return static_cast<ValueType>(static_cast<UnsignedValueType>(value) >> shift);
382 }
383
384 return ValueType{0};
385}
386
387/**
388 * @ingroup bits
389 * Performs a right logical bit shift operation (`shr`, `>>>` in Java). Fills the left bits by zero.
390 *
391 * The result of the shift will be of the same type as the `value` being shifted.
392 * If the shift is a negative number of bits, then a @ref ::shl() "left logical shift" will be performed.
393 * If the shift size is greater than or equal to the number of bits in the shifted `value`, then `0` will be
394 * returned.
395 *
396 * @tparam ValueType The type of `value`
397 * @tparam ShiftType The type of `shift`
398 * @param value The value to be shifted.
399 * @param shift The shift in bits
400 * @return The shifted `value`
401 */
402template <std::integral ValueType, std::integral ShiftType>
403constexpr ValueType shr(ValueType value, ShiftType shift) noexcept {
404 return rightLogicalShift(value, shift);
405}
406
407/**
408 * @ingroup bits
409 * Performs a bitwise AND operation between two values of possibly different types
410 * and ensures the result is cast back to the type of the first argument.
411 *
412 * @tparam FirstType The type of the first argument.
413 * @tparam SecondType The type of the second argument.
414 * @param first The first operand of type `FirstType`.
415 * @param second The second operand of type `SecondType`.
416 * @return The result of the bitwise AND operation, cast to type `FirstType`.
417 */
418template <std::integral FirstType, std::integral SecondType>
419constexpr FirstType andOp(FirstType first, SecondType second) noexcept {
420 using MaxUnsignedType = std::make_unsigned_t<Max<FirstType, SecondType>>;
421
422 return static_cast<FirstType>(static_cast<MaxUnsignedType>(first) & static_cast<MaxUnsignedType>(second));
423}
424
425/**
426 * @ingroup bits
427 * Performs a bitwise OR operation between two values of possibly different types
428 * and ensures the result is cast back to the type of the first argument.
429 *
430 * @tparam FirstType The type of the first argument.
431 * @tparam SecondType The type of the second argument.
432 * @param first The first operand of type `FirstType`.
433 * @param second The second operand of type `SecondType`.
434 * @return The result of the bitwise OR operation, cast to type `FirstType`.
435 */
436template <std::integral FirstType, std::integral SecondType>
437constexpr FirstType orOp(FirstType first, SecondType second) noexcept {
438 using MaxUnsignedType = std::make_unsigned_t<Max<FirstType, SecondType>>;
439
440 return static_cast<FirstType>(static_cast<MaxUnsignedType>(first) | static_cast<MaxUnsignedType>(second));
441}
442
443/**
444 * @ingroup bits
445 * Performs a bitwise XOR operation between two values of possibly different types
446 * and ensures the result is cast back to the type of the first argument.
447 *
448 * @tparam FirstType The type of the first argument.
449 * @tparam SecondType The type of the second argument.
450 * @param first The first operand of type `FirstType`.
451 * @param second The second operand of type `SecondType`.
452 * @return The result of the bitwise XOR operation, cast to type `FirstType`.
453 */
454template <std::integral FirstType, std::integral SecondType>
455constexpr FirstType xorOp(FirstType first, SecondType second) noexcept {
456 using MaxUnsignedType = std::make_unsigned_t<Max<FirstType, SecondType>>;
457
458 return static_cast<FirstType>(static_cast<MaxUnsignedType>(first) ^ static_cast<MaxUnsignedType>(second));
459}
460
461/**
462 * @ingroup bits
463 * Determines if the specified bits are set in the source value.
464 *
465 * @tparam T the type of arguments.
466 * @param sourceBits The value to check for the presence of specific bits.
467 * @param bitMaskToCheck The mask of bits to check against the source value.
468 * @return `true` if the specified bits are set in the source value.
469 */
470template <std::unsigned_integral T>
471constexpr bool bitsAreSet(T sourceBits, T bitMaskToCheck) {
472 return andOp(sourceBits, bitMaskToCheck) != 0;
473}
474
475/**
476 * @ingroup bits
477 * Determines if the specified bits are set in the source value.
478 *
479 * @tparam SourceBitsType The type of the source bits (e.g., an integer type).
480 * @tparam BitMaskType The type of the bit mask (e.g., an integer type).
481 * @param sourceBits The value to check for the presence of specific bits.
482 * @param bitMaskToCheck The mask of bits to check against the source value.
483 * @return `true` if the specified bits are set in the source value.
484 */
485template <std::integral SourceBitsType, std::integral BitMaskType>
486constexpr bool bitsAreSet(SourceBitsType sourceBits, BitMaskType bitMaskToCheck) {
487 using MaxType = Max<SourceBitsType, BitMaskType>;
488
489 if constexpr (std::is_signed_v<SourceBitsType> || std::is_signed_v<BitMaskType>) {
490 using MaxUnsignedType = std::make_unsigned_t<MaxType>;
491
492 return bitsAreSet(static_cast<MaxUnsignedType>(sourceBits), static_cast<MaxUnsignedType>(bitMaskToCheck));
493 } else {
494 return bitsAreSet(static_cast<MaxType>(sourceBits), static_cast<MaxType>(bitMaskToCheck));
495 }
496}
497
498/**
499 * @ingroup bits
500 * Sets specific bits in the source value using a bitmask.
501 *
502 * @tparam T The type of arguments.
503 * @param sourceBits The original bits to modify.
504 * @param bitMaskToSet The bitmask representing the bits to be set.
505 * @return The resulting value after setting the specified bits.
506 */
507template <std::unsigned_integral T>
508constexpr T setBits(T sourceBits, T bitMaskToSet) {
509 return orOp(sourceBits, bitMaskToSet);
510}
511
512/**
513 * @ingroup bits
514 * Sets specific bits in the source value using a bitmask.
515 *
516 * @tparam SourceBitsType The type of the source bits (e.g., an integer type).
517 * @tparam BitMaskType The type of the bit mask (e.g., an integer type).
518 * @param sourceBits The original bits to modify.
519 * @param bitMaskToSet The bitmask representing the bits to be set.
520 * @return The resulting value after setting the specified bits.
521 */
522template <std::integral SourceBitsType, std::integral BitMaskType>
523constexpr SourceBitsType setBits(SourceBitsType sourceBits, BitMaskType bitMaskToSet) {
524 using MaxType = Max<SourceBitsType, BitMaskType>;
525
526 if constexpr (std::is_signed_v<SourceBitsType> || std::is_signed_v<BitMaskType>) {
527 using MaxUnsignedType = std::make_unsigned_t<MaxType>;
528
529 return static_cast<SourceBitsType>(
530 setBits(static_cast<MaxUnsignedType>(sourceBits), static_cast<MaxUnsignedType>(bitMaskToSet)));
531 } else {
532 return static_cast<SourceBitsType>(setBits(static_cast<MaxType>(sourceBits), static_cast<MaxType>(bitMaskToSet)));
533 }
534}
535
536/**
537 * @ingroup bits
538 * Resets (clears) specific bits in a bitmask.
539 *
540 * @tparam T The type of the source bits and the bitmask. Should be an integral type.
541 * @param sourceBits The original bitmask containing the bits to modify.
542 * @param bitMaskToReset The bitmask specifying the bits to reset.
543 * @return The resulting value after resetting the specified bits.
544 */
545template <std::unsigned_integral T>
546constexpr T resetBits(T sourceBits, T bitMaskToReset) {
547 return andOp(sourceBits, ~bitMaskToReset);
548}
549
550/**
551 * @ingroup bits
552 * Resets (clears) specific bits in a bitmask.
553 *
554 * @tparam SourceBitsType The type of the source bits (e.g., an integer type).
555 * @tparam BitMaskType The type of the bit mask (e.g., an integer type).
556 * @param sourceBits The original bitmask containing the bits to modify.
557 * @param bitMaskToReset The bitmask specifying the bits to reset.
558 * @return The resulting value after resetting the specified bits.
559 */
560template <std::integral SourceBitsType, std::integral BitMaskType>
561// ReSharper disable once CppDFAConstantParameter
562constexpr SourceBitsType resetBits(SourceBitsType sourceBits, BitMaskType bitMaskToReset) {
563 using MaxType = Max<SourceBitsType, BitMaskType>;
564
565 if constexpr (std::is_signed_v<SourceBitsType> || std::is_signed_v<BitMaskType>) {
566 using MaxUnsignedType = std::make_unsigned_t<MaxType>;
567
568 return static_cast<SourceBitsType>(
569 resetBits(static_cast<MaxUnsignedType>(sourceBits), static_cast<MaxUnsignedType>(bitMaskToReset)));
570 } else {
571 return static_cast<SourceBitsType>(
572 resetBits(static_cast<MaxType>(sourceBits), static_cast<MaxType>(bitMaskToReset)));
573 }
574}
575
576} // namespace org::ttldtor::bits
577
578/**@}*/
constexpr bool bitsAreSet(T sourceBits, T bitMaskToCheck)
Determines if the specified bits are set in the source value.
Definition bits.hpp:471
constexpr T setBits(T sourceBits, T bitMaskToSet)
Sets specific bits in the source value using a bitmask.
Definition bits.hpp:508
constexpr ValueType shl(ValueType value, ShiftType shift) noexcept
Performs a left logical bit shift operation (shl, <<<).
Definition bits.hpp:318
constexpr SourceBitsType setBits(SourceBitsType sourceBits, BitMaskType bitMaskToSet)
Sets specific bits in the source value using a bitmask.
Definition bits.hpp:523
constexpr ValueType rightArithmeticShift(ValueType value, UnsignedShiftType shift) noexcept
Performs a right arithmetic bit shift operation (sar, >> in Java, C, etc.).
Definition bits.hpp:159
constexpr ValueType shr(ValueType value, ShiftType shift) noexcept
Performs a right logical bit shift operation (>>> in Java).
Definition bits.hpp:403
constexpr SourceBitsType resetBits(SourceBitsType sourceBits, BitMaskType bitMaskToReset)
Resets (clears) specific bits in a bitmask.
Definition bits.hpp:562
constexpr ValueType sal(ValueType value, ShiftType shift) noexcept
Performs a left arithmetic bit shift operation (<< in Java, C, etc.).
Definition bits.hpp:139
constexpr T resetBits(T sourceBits, T bitMaskToReset)
Resets (clears) specific bits in a bitmask.
Definition bits.hpp:546
constexpr ValueType leftArithmeticShift(ValueType value, UnsignedShiftType shift) noexcept
Performs a left arithmetic bit shift operation (sal, << in Java, C, etc.).
Definition bits.hpp:76
constexpr bool bitsAreSet(SourceBitsType sourceBits, BitMaskType bitMaskToCheck)
Determines if the specified bits are set in the source value.
Definition bits.hpp:486
constexpr ValueType rightLogicalShift(ValueType value, UnsignedShiftType shift) noexcept
Performs a right logical bit shift operation (shr, >>> in Java).
Definition bits.hpp:339
constexpr ValueType leftLogicalShift(ValueType value, UnsignedShiftType shift) noexcept
Performs a left logical bit shift operation (shl, <<<).
Definition bits.hpp:262
constexpr FirstType andOp(FirstType first, SecondType second) noexcept
Performs a bitwise AND operation between two values of possibly different types and ensures the resul...
Definition bits.hpp:419
constexpr ValueType sar(ValueType value, ShiftType shift) noexcept
Performs a right arithmetic bit shift operation (>> in Java, C, etc.).
Definition bits.hpp:224
constexpr FirstType orOp(FirstType first, SecondType second) noexcept
Performs a bitwise OR operation between two values of possibly different types and ensures the result...
Definition bits.hpp:437
constexpr FirstType xorOp(FirstType first, SecondType second) noexcept
Performs a bitwise XOR operation between two values of possibly different types and ensures the resul...
Definition bits.hpp:455