aboutsummaryrefslogtreecommitdiffstats
path: root/util/generic/bitops_ut.cpp
blob: d23c2b5c27e140d1e2197382052c44366e0e7d72 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
#include "bitops.h"

#include <library/cpp/testing/unittest/registar.h>

#include <util/string/builder.h>

template <typename T>
static void TestCTZ() {
    for (unsigned int i = 0; i < (sizeof(T) << 3); ++i) {
        UNIT_ASSERT_VALUES_EQUAL(CountTrailingZeroBits(T(1) << i), i);
    }
}

template <typename T>
static void TestFastClp2ForEachPowerOf2() {
    for (size_t i = 0; i < sizeof(T) * 8 - 1; ++i) {
        const auto current = T(1) << i;
        UNIT_ASSERT_VALUES_EQUAL(FastClp2(current), current);
    }

    UNIT_ASSERT_VALUES_EQUAL(FastClp2(T(1)), T(1));
    for (size_t i = 1; i < sizeof(T) * 8 - 1; ++i) {
        for (size_t j = 0; j < i; ++j) {
            const auto value = (T(1) << i) | (T(1) << j);
            const auto next = T(1) << (i + 1);
            UNIT_ASSERT_VALUES_EQUAL(FastClp2(value), next);
        }
    }
}

template <typename T>
static T ReverseBitsSlow(T v) {
    T r = v;                    // r will be reversed bits of v; first get LSB of v
    ui32 s = sizeof(v) * 8 - 1; // extra shift needed at end

    for (v >>= 1; v; v >>= 1) {
        r <<= 1;
        r |= v & 1;
        --s;
    }

    r <<= s; // shift when v's highest bits are zero
    return r;
}

// DO_NOT_STYLE
Y_UNIT_TEST_SUITE(TBitOpsTest) {
    Y_UNIT_TEST(TestCountTrailingZeroBits) {
        TestCTZ<unsigned int>();
        TestCTZ<unsigned long>();
        TestCTZ<unsigned long long>();
    }

    Y_UNIT_TEST(TestIsPowerOf2) {
        UNIT_ASSERT(!IsPowerOf2(-2));
        UNIT_ASSERT(!IsPowerOf2(-1));
        UNIT_ASSERT(!IsPowerOf2(0));
        UNIT_ASSERT(IsPowerOf2(1));
        UNIT_ASSERT(IsPowerOf2(2));
        UNIT_ASSERT(!IsPowerOf2(3));
        UNIT_ASSERT(IsPowerOf2(4));
        UNIT_ASSERT(!IsPowerOf2(5));
        UNIT_ASSERT(IsPowerOf2(0x10000000u));
        UNIT_ASSERT(!IsPowerOf2(0x10000001u));
        UNIT_ASSERT(IsPowerOf2(0x1000000000000000ull));
        UNIT_ASSERT(!IsPowerOf2(0x1000000000000001ull));
    }

    Y_UNIT_TEST(TestFastClp2) {
        TestFastClp2ForEachPowerOf2<unsigned>();
        TestFastClp2ForEachPowerOf2<unsigned long>();
        TestFastClp2ForEachPowerOf2<unsigned long long>();
    }

    Y_UNIT_TEST(TestMask) {
        for (ui32 i = 0; i < 64; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(MaskLowerBits(i), (ui64{1} << i) - 1);
            UNIT_ASSERT_VALUES_EQUAL(InverseMaskLowerBits(i), ~MaskLowerBits(i));
            UNIT_ASSERT_VALUES_EQUAL(MaskLowerBits(i, i / 2), (ui64{1} << i) - 1 << (i / 2));
            UNIT_ASSERT_VALUES_EQUAL(InverseMaskLowerBits(i, i / 2), ~MaskLowerBits(i, i / 2));
        }
    }

    Y_UNIT_TEST(TestMostSignificantBit) {
        static_assert(MostSignificantBitCT(0) == 0, ".");
        static_assert(MostSignificantBitCT(1) == 0, ".");
        static_assert(MostSignificantBitCT(5) == 2, ".");

        for (ui32 i = 0; i < 64; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(i, MostSignificantBit(ui64{1} << i));
        }

        for (ui32 i = 0; i < 63; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(i + 1, MostSignificantBit(ui64{3} << i));
        }
    }

    Y_UNIT_TEST(TestLeastSignificantBit) {
        for (ui32 i = 0; i < 64; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(i, LeastSignificantBit(ui64{1} << i));
        }

        for (ui32 i = 0; i < 63; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(i, LeastSignificantBit(ui64{3} << i));
        }

        for (ui32 i = 0; i < 64; ++i) {
            ui64 value = (ui64(-1)) << i;
            UNIT_ASSERT_VALUES_EQUAL(i, LeastSignificantBit(value));
        }
    }

    Y_UNIT_TEST(TestCeilLog2) {
        UNIT_ASSERT_VALUES_EQUAL(CeilLog2(ui64{1}), 1);

        for (ui32 i = 2; i < 64; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(CeilLog2(ui64{1} << i), i);
            UNIT_ASSERT_VALUES_EQUAL(CeilLog2((ui64{1} << i) | ui64{1}), i + 1);
        }
    }

    Y_UNIT_TEST(TestReverse) {
        for (ui64 i = 0; i < 0x100; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui8)i), ReverseBitsSlow((ui8)i));
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui16)i), ReverseBitsSlow((ui16)i));
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui32)i), ReverseBitsSlow((ui32)i));
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui64)i), ReverseBitsSlow((ui64)i));
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui16)~i), ReverseBitsSlow((ui16)~i));
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui32)~i), ReverseBitsSlow((ui32)~i));
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits((ui64)~i), ReverseBitsSlow((ui64)~i));
        }

        ui32 v = 0xF0F0F0F0; // 11110000111100001111000011110000
        for (ui32 i = 0; i < 4; ++i) {
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits(v, i + 1), v);
            UNIT_ASSERT_VALUES_EQUAL(ReverseBits(v, 4 + 2 * i, 4 - i), v);
        }

        UNIT_ASSERT_VALUES_EQUAL(ReverseBits(v, 8), 0xF0F0F00Fu);
        UNIT_ASSERT_VALUES_EQUAL(ReverseBits(v, 8, 4), 0xF0F0FF00u);

        for (ui32 i = 0; i < 0x10000; ++i) {
            for (ui32 j = 0; j <= 32; ++j) {
                UNIT_ASSERT_VALUES_EQUAL_C(i, ReverseBits(ReverseBits(i, j), j), (TString)(TStringBuilder() << i << " " << j));
            }
        }
    }

    Y_UNIT_TEST(TestRotateBitsLeft) {
        static_assert(RotateBitsLeftCT<ui8>(0b00000000u, 0) == 0b00000000u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b00000001u, 0) == 0b00000001u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b10000000u, 0) == 0b10000000u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b00000001u, 1) == 0b00000010u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b10000000u, 1) == 0b00000001u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b00000101u, 1) == 0b00001010u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b10100000u, 1) == 0b01000001u, "");
        static_assert(RotateBitsLeftCT<ui8>(0b10000000u, 7) == 0b01000000u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b00000000u, 0), 0b00000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b00000001u, 0), 0b00000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b10000000u, 0), 0b10000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b00000001u, 1), 0b00000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b10000000u, 1), 0b00000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b00000101u, 1), 0b00001010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b10100000u, 1), 0b01000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui8>(0b10000000u, 7), 0b01000000u);

        static_assert(RotateBitsLeftCT<ui16>(0b0000000000000000u, 0) == 0b0000000000000000u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b0000000000000001u, 0) == 0b0000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b1000000000000000u, 0) == 0b1000000000000000u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b0000000000000001u, 1) == 0b0000000000000010u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b1000000000000000u, 1) == 0b0000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b0000000000000101u, 1) == 0b0000000000001010u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b1010000000000000u, 1) == 0b0100000000000001u, "");
        static_assert(RotateBitsLeftCT<ui16>(0b1000000000000000u, 15) == 0b0100000000000000u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b0000000000000000u, 0), 0b0000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b0000000000000001u, 0), 0b0000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b1000000000000000u, 0), 0b1000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b0000000000000001u, 1), 0b0000000000000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b1000000000000000u, 1), 0b0000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b0000000000000101u, 1), 0b0000000000001010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b1010000000000000u, 1), 0b0100000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui16>(0b1000000000000000u, 15), 0b0100000000000000u);

        static_assert(RotateBitsLeftCT<ui32>(0b00000000000000000000000000000000u, 0) == 0b00000000000000000000000000000000u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b00000000000000000000000000000001u, 0) == 0b00000000000000000000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b10000000000000000000000000000000u, 0) == 0b10000000000000000000000000000000u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b00000000000000000000000000000001u, 1) == 0b00000000000000000000000000000010u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b10000000000000000000000000000000u, 1) == 0b00000000000000000000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b00000000000000000000000000000101u, 1) == 0b00000000000000000000000000001010u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b10100000000000000000000000000000u, 1) == 0b01000000000000000000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui32>(0b10000000000000000000000000000000u, 31) == 0b01000000000000000000000000000000u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b00000000000000000000000000000000u, 0), 0b00000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b00000000000000000000000000000001u, 0), 0b00000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b10000000000000000000000000000000u, 0), 0b10000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b00000000000000000000000000000001u, 1), 0b00000000000000000000000000000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b10000000000000000000000000000000u, 1), 0b00000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b00000000000000000000000000000101u, 1), 0b00000000000000000000000000001010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b10100000000000000000000000000000u, 1), 0b01000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui32>(0b10000000000000000000000000000000u, 31), 0b01000000000000000000000000000000u);

        static_assert(RotateBitsLeftCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000000u, 0) == 0b0000000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 0) == 0b0000000000000000000000000000000000000000000000000000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 0) == 0b1000000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 1) == 0b0000000000000000000000000000000000000000000000000000000000000010u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 1) == 0b0000000000000000000000000000000000000000000000000000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000101u, 1) == 0b0000000000000000000000000000000000000000000000000000000000001010u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b1010000000000000000000000000000000000000000000000000000000000000u, 1) == 0b0100000000000000000000000000000000000000000000000000000000000001u, "");
        static_assert(RotateBitsLeftCT<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 63) == 0b0100000000000000000000000000000000000000000000000000000000000000u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b0000000000000000000000000000000000000000000000000000000000000000u, 0), 0b0000000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 0), 0b0000000000000000000000000000000000000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 0), 0b1000000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 1), 0b0000000000000000000000000000000000000000000000000000000000000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 1), 0b0000000000000000000000000000000000000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b0000000000000000000000000000000000000000000000000000000000000101u, 1), 0b0000000000000000000000000000000000000000000000000000000000001010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b1010000000000000000000000000000000000000000000000000000000000000u, 1), 0b0100000000000000000000000000000000000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsLeft<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 63), 0b0100000000000000000000000000000000000000000000000000000000000000u);
    }

    Y_UNIT_TEST(TestRotateBitsRight) {
        static_assert(RotateBitsRightCT<ui8>(0b00000000u, 0) == 0b00000000u, "");
        static_assert(RotateBitsRightCT<ui8>(0b00000001u, 0) == 0b00000001u, "");
        static_assert(RotateBitsRightCT<ui8>(0b10000000u, 0) == 0b10000000u, "");
        static_assert(RotateBitsRightCT<ui8>(0b00000001u, 1) == 0b10000000u, "");
        static_assert(RotateBitsRightCT<ui8>(0b10000000u, 1) == 0b01000000u, "");
        static_assert(RotateBitsRightCT<ui8>(0b00000101u, 1) == 0b10000010u, "");
        static_assert(RotateBitsRightCT<ui8>(0b10100000u, 1) == 0b01010000u, "");
        static_assert(RotateBitsRightCT<ui8>(0b00000001u, 7) == 0b00000010u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b00000000u, 0), 0b00000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b00000001u, 0), 0b00000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b10000000u, 0), 0b10000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b00000001u, 1), 0b10000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b10000000u, 1), 0b01000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b00000101u, 1), 0b10000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b10100000u, 1), 0b01010000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui8>(0b00000001u, 7), 0b00000010u);

        static_assert(RotateBitsRightCT<ui16>(0b0000000000000000u, 0) == 0b0000000000000000u, "");
        static_assert(RotateBitsRightCT<ui16>(0b0000000000000001u, 0) == 0b0000000000000001u, "");
        static_assert(RotateBitsRightCT<ui16>(0b1000000000000000u, 0) == 0b1000000000000000u, "");
        static_assert(RotateBitsRightCT<ui16>(0b0000000000000001u, 1) == 0b1000000000000000u, "");
        static_assert(RotateBitsRightCT<ui16>(0b1000000000000000u, 1) == 0b0100000000000000u, "");
        static_assert(RotateBitsRightCT<ui16>(0b0000000000000101u, 1) == 0b1000000000000010u, "");
        static_assert(RotateBitsRightCT<ui16>(0b1010000000000000u, 1) == 0b0101000000000000u, "");
        static_assert(RotateBitsRightCT<ui16>(0b0000000000000001u, 15) == 0b0000000000000010u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b0000000000000000u, 0), 0b0000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b0000000000000001u, 0), 0b0000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b1000000000000000u, 0), 0b1000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b0000000000000001u, 1), 0b1000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b1000000000000000u, 1), 0b0100000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b0000000000000101u, 1), 0b1000000000000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b1010000000000000u, 1), 0b0101000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui16>(0b0000000000000001u, 15), 0b0000000000000010u);

        static_assert(RotateBitsRightCT<ui32>(0b00000000000000000000000000000000u, 0) == 0b00000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui32>(0b00000000000000000000000000000001u, 0) == 0b00000000000000000000000000000001u, "");
        static_assert(RotateBitsRightCT<ui32>(0b10000000000000000000000000000000u, 0) == 0b10000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui32>(0b00000000000000000000000000000001u, 1) == 0b10000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui32>(0b10000000000000000000000000000000u, 1) == 0b01000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui32>(0b00000000000000000000000000000101u, 1) == 0b10000000000000000000000000000010u, "");
        static_assert(RotateBitsRightCT<ui32>(0b10100000000000000000000000000000u, 1) == 0b01010000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui32>(0b00000000000000000000000000000001u, 31) == 0b00000000000000000000000000000010u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b00000000000000000000000000000000u, 0), 0b00000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b00000000000000000000000000000001u, 0), 0b00000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b10000000000000000000000000000000u, 0), 0b10000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b00000000000000000000000000000001u, 1), 0b10000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b10000000000000000000000000000000u, 1), 0b01000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b00000000000000000000000000000101u, 1), 0b10000000000000000000000000000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b10100000000000000000000000000000u, 1), 0b01010000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui32>(0b00000000000000000000000000000001u, 31), 0b00000000000000000000000000000010u);

        static_assert(RotateBitsRightCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000000u, 0) == 0b0000000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 0) == 0b0000000000000000000000000000000000000000000000000000000000000001u, "");
        static_assert(RotateBitsRightCT<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 0) == 0b1000000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 1) == 0b1000000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 1) == 0b0100000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000101u, 1) == 0b1000000000000000000000000000000000000000000000000000000000000010u, "");
        static_assert(RotateBitsRightCT<ui64>(0b1010000000000000000000000000000000000000000000000000000000000000u, 1) == 0b0101000000000000000000000000000000000000000000000000000000000000u, "");
        static_assert(RotateBitsRightCT<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 63) == 0b0000000000000000000000000000000000000000000000000000000000000010u, "");

        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b0000000000000000000000000000000000000000000000000000000000000000u, 0), 0b0000000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 0), 0b0000000000000000000000000000000000000000000000000000000000000001u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 0), 0b1000000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 1), 0b1000000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b1000000000000000000000000000000000000000000000000000000000000000u, 1), 0b0100000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b0000000000000000000000000000000000000000000000000000000000000101u, 1), 0b1000000000000000000000000000000000000000000000000000000000000010u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b1010000000000000000000000000000000000000000000000000000000000000u, 1), 0b0101000000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(RotateBitsRight<ui64>(0b0000000000000000000000000000000000000000000000000000000000000001u, 63), 0b0000000000000000000000000000000000000000000000000000000000000010u);
    }

    Y_UNIT_TEST(TestSelectBits) {
        ui8 firstui8Test = SelectBits<3, 4, ui8>(0b11111111u);
        ui8 secondui8Test = SelectBits<2, 5, ui8>(0b11101101u);
        UNIT_ASSERT_VALUES_EQUAL(firstui8Test, 0b00001111u);
        UNIT_ASSERT_VALUES_EQUAL(secondui8Test, 0b00011011u);

        ui16 firstui16Test = SelectBits<9, 2, ui16>(0b1111111111111111u);
        ui16 secondui16Test = SelectBits<3, 6, ui16>(0b1010011111010001u);
        UNIT_ASSERT_VALUES_EQUAL(firstui16Test, 0b0000000000000011u);
        UNIT_ASSERT_VALUES_EQUAL(secondui16Test, 0b0000000000111010u);

        ui32 firstui32Test = SelectBits<23, 31, ui32>(0b11111111111111111111111111111111u);
        ui32 secondui32Test = SelectBits<0, 31, ui32>(0b10001011101010011111010000111111u);
        UNIT_ASSERT_VALUES_EQUAL(firstui32Test, 0b00000000000000000000000111111111u);
        UNIT_ASSERT_VALUES_EQUAL(secondui32Test, 0b00001011101010011111010000111111);

        ui64 firstui64Test = SelectBits<1, 62, ui64>(0b1111000000000000000000000000000000000000000000000000000000000000u);
        ui64 secondui64Test = SelectBits<32, 43, ui64>(0b1111111111111111111111111111111111111111111111111111111111111111u);
        UNIT_ASSERT_VALUES_EQUAL(firstui64Test, 0b0011100000000000000000000000000000000000000000000000000000000000u);
        UNIT_ASSERT_VALUES_EQUAL(secondui64Test, 0b0000000000000000000000000000000011111111111111111111111111111111u);
    }

    Y_UNIT_TEST(TestSetBits) {
        ui8 firstui8Test = 0b11111111u;
        SetBits<3, 4, ui8>(firstui8Test, 0b00001111u);
        ui8 secondui8Test = 0b11101101u;
        SetBits<2, 7, ui8>(secondui8Test, 0b01110111u);
        UNIT_ASSERT_VALUES_EQUAL(firstui8Test, 0b11111111u);
        UNIT_ASSERT_VALUES_EQUAL(secondui8Test, 0b11011101u);

        ui16 firstui16Test = 0b1111111111111111u;
        SetBits<9, 4, ui16>(firstui16Test, 0b000000000000111u);
        ui16 secondui16Test = 0b1010011111010001u;
        SetBits<3, 15, ui16>(secondui16Test, 0b0010011111010001u);
        UNIT_ASSERT_VALUES_EQUAL(firstui16Test, 0b1110111111111111u);
        UNIT_ASSERT_VALUES_EQUAL(secondui16Test, 0b0011111010001001u);

        ui32 firstui32Test = 0b11111111111111111111111111111111u;
        SetBits<23, 31, ui32>(firstui32Test, 0b01100001111111111001111101111111u);
        ui32 secondui32Test = 0b10001011101010011111010000111111u;
        SetBits<0, 31, ui32>(secondui32Test, 0b01111111111111111111111111111111u);
        UNIT_ASSERT_VALUES_EQUAL(firstui32Test, 0b10111111111111111111111111111111u);
        UNIT_ASSERT_VALUES_EQUAL(secondui32Test, 0b11111111111111111111111111111111u);

        ui64 firstui64Test = 0b1111000000000000000000000000000000000000000000000000000000000000u;
        SetBits<1, 62, ui64>(firstui64Test, 0b0001000000000000000000000000000000000000000000000000000001010101u);
        ui64 secondui64Test = 0b1111111111111111111111111111111111111111111111111111111111111111u;
        SetBits<32, 43, ui64>(secondui64Test, 0b0000000000000000000000000000000000000111111111111111111111111111u);
        UNIT_ASSERT_VALUES_EQUAL(firstui64Test, 0b1010000000000000000000000000000000000000000000000000000010101010u);
        UNIT_ASSERT_VALUES_EQUAL(secondui64Test, 0b0000011111111111111111111111111111111111111111111111111111111111u);
    }
};