5
6
7
8
17
18
21namespace org::ttldtor::bits {
24template <
typename T,
typename...>
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;
36
37
38
39template <
typename... Ts>
40using Max = detail::MaxImpl<Ts...>::Type;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58template <std::integral ValueType, std::integral ShiftType>
59constexpr ValueType sar(ValueType value, ShiftType shift)
noexcept;
62
63
64
65
66
67
68
69
70
71
72
73
74
75template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
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);
80 if (shift < MAX_VALUE_BITS) {
81 return static_cast<ValueType>(
static_cast<UnsignedValueType>(value) << shift);
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102template <std::integral ValueType, std::signed_integral SignedShiftType>
104 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
107 const UnsignedShiftType magnitude = UnsignedShiftType{0} -
static_cast<UnsignedShiftType>(shift);
109 return sar(value, magnitude);
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);
116 if (unsignedShift < MAX_VALUE_BITS) {
117 return static_cast<ValueType>(
static_cast<UnsignedValueType>(value) << unsignedShift);
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138template <std::integral ValueType, std::integral ShiftType>
140 return leftArithmeticShift(value, shift);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
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);
163 if (shift < MAX_VALUE_BITS) {
164 return static_cast<ValueType>(value >> shift);
167 return value < 0 ?
static_cast<ValueType>(-1) : ValueType{0};
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186template <std::integral ValueType, std::signed_integral SignedShiftType>
188 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
191 const UnsignedShiftType magnitude = UnsignedShiftType{0} -
static_cast<UnsignedShiftType>(shift);
193 return sal(value, magnitude);
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);
200 if (unsignedShift < MAX_VALUE_BITS) {
201 return static_cast<ValueType>(value >> unsignedShift);
204 return value < 0 ?
static_cast<ValueType>(-1) : ValueType{0};
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223template <std::integral ValueType, std::integral ShiftType>
225 return rightArithmeticShift(value, shift);
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243template <std::integral ValueType, std::integral ShiftType>
244constexpr ValueType shr(ValueType value, ShiftType shift)
noexcept;
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
263 return leftArithmeticShift(value, shift);
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281template <std::integral ValueType, std::integral SignedShiftType>
283 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
286 const UnsignedShiftType magnitude = UnsignedShiftType{0} -
static_cast<UnsignedShiftType>(shift);
288 return shr(value, magnitude);
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);
295 if (unsignedShift < MAX_VALUE_BITS) {
296 return static_cast<ValueType>(
static_cast<UnsignedValueType>(value) << unsignedShift);
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317template <std::integral ValueType, std::integral ShiftType>
319 return leftLogicalShift(value, shift);
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338template <std::integral ValueType, std::unsigned_integral UnsignedShiftType>
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);
343 if (shift < MAX_VALUE_BITS) {
344 return static_cast<ValueType>(
static_cast<UnsignedValueType>(value) >> shift);
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366template <std::integral ValueType, std::signed_integral SignedShiftType>
368 using UnsignedShiftType = std::make_unsigned_t<std::remove_cv_t<SignedShiftType>>;
371 const UnsignedShiftType magnitude = UnsignedShiftType{0} -
static_cast<UnsignedShiftType>(shift);
373 return shl(value, magnitude);
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);
380 if (unsignedShift < MAX_VALUE_BITS) {
381 return static_cast<ValueType>(
static_cast<UnsignedValueType>(value) >> shift);
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402template <std::integral ValueType, std::integral ShiftType>
404 return rightLogicalShift(value, shift);
408
409
410
411
412
413
414
415
416
417
418template <std::integral FirstType, std::integral SecondType>
420 using MaxUnsignedType = std::make_unsigned_t<Max<FirstType, SecondType>>;
422 return static_cast<FirstType>(
static_cast<MaxUnsignedType>(first) &
static_cast<MaxUnsignedType>(second));
426
427
428
429
430
431
432
433
434
435
436template <std::integral FirstType, std::integral SecondType>
438 using MaxUnsignedType = std::make_unsigned_t<Max<FirstType, SecondType>>;
440 return static_cast<FirstType>(
static_cast<MaxUnsignedType>(first) |
static_cast<MaxUnsignedType>(second));
444
445
446
447
448
449
450
451
452
453
454template <std::integral FirstType, std::integral SecondType>
456 using MaxUnsignedType = std::make_unsigned_t<Max<FirstType, SecondType>>;
458 return static_cast<FirstType>(
static_cast<MaxUnsignedType>(first) ^
static_cast<MaxUnsignedType>(second));
462
463
464
465
466
467
468
469
470template <std::unsigned_integral T>
472 return andOp(sourceBits, bitMaskToCheck) != 0;
476
477
478
479
480
481
482
483
484
485template <std::integral SourceBitsType, std::integral BitMaskType>
486constexpr bool bitsAreSet(SourceBitsType sourceBits, BitMaskType bitMaskToCheck) {
487 using MaxType = Max<SourceBitsType, BitMaskType>;
489 if constexpr (std::is_signed_v<SourceBitsType> || std::is_signed_v<BitMaskType>) {
490 using MaxUnsignedType = std::make_unsigned_t<MaxType>;
492 return bitsAreSet(
static_cast<MaxUnsignedType>(sourceBits),
static_cast<MaxUnsignedType>(bitMaskToCheck));
494 return bitsAreSet(
static_cast<MaxType>(sourceBits),
static_cast<MaxType>(bitMaskToCheck));
499
500
501
502
503
504
505
506
507template <std::unsigned_integral T>
509 return orOp(sourceBits, bitMaskToSet);
513
514
515
516
517
518
519
520
521
522template <std::integral SourceBitsType, std::integral BitMaskType>
524 using MaxType = Max<SourceBitsType, BitMaskType>;
526 if constexpr (std::is_signed_v<SourceBitsType> || std::is_signed_v<BitMaskType>) {
527 using MaxUnsignedType = std::make_unsigned_t<MaxType>;
529 return static_cast<SourceBitsType>(
530 setBits(
static_cast<MaxUnsignedType>(sourceBits),
static_cast<MaxUnsignedType>(bitMaskToSet)));
532 return static_cast<SourceBitsType>(setBits(
static_cast<MaxType>(sourceBits),
static_cast<MaxType>(bitMaskToSet)));
537
538
539
540
541
542
543
544
545template <std::unsigned_integral T>
547 return andOp(sourceBits, ~bitMaskToReset);
551
552
553
554
555
556
557
558
559
560template <std::integral SourceBitsType, std::integral BitMaskType>
563 using MaxType = Max<SourceBitsType, BitMaskType>;
565 if constexpr (std::is_signed_v<SourceBitsType> || std::is_signed_v<BitMaskType>) {
566 using MaxUnsignedType = std::make_unsigned_t<MaxType>;
568 return static_cast<SourceBitsType>(
569 resetBits(
static_cast<MaxUnsignedType>(sourceBits),
static_cast<MaxUnsignedType>(bitMaskToReset)));
571 return static_cast<SourceBitsType>(
572 resetBits(
static_cast<MaxType>(sourceBits),
static_cast<MaxType>(bitMaskToReset)));
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