Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
get_msb.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Luke], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
8#include <array>
9#include <cassert>
10#include <cstddef>
11#include <cstdint>
12#include <limits>
13namespace bb::numeric {
14
15// De Bruijn MSB. Returns 0 for input 0 (by convention; many callers rely on this).
16// from http://supertech.csail.mit.edu/papers/debruijn.pdf
17constexpr inline uint32_t get_msb32(const uint32_t in)
18{
19 constexpr std::array<uint8_t, 32> MultiplyDeBruijnBitPosition{ 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16,
20 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17,
21 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 };
22
23 uint32_t v = in | (in >> 1);
24 v |= v >> 2;
25 v |= v >> 4;
26 v |= v >> 8;
27 v |= v >> 16;
28
29 return MultiplyDeBruijnBitPosition[static_cast<uint32_t>(v * static_cast<uint32_t>(0x07C4ACDD)) >>
30 static_cast<uint32_t>(27)];
31}
32
33constexpr inline uint64_t get_msb64(const uint64_t in)
34{
35 constexpr std::array<uint8_t, 64> de_bruijn_sequence{ 0, 47, 1, 56, 48, 27, 2, 60, 57, 49, 41, 37, 28,
36 16, 3, 61, 54, 58, 35, 52, 50, 42, 21, 44, 38, 32,
37 29, 23, 17, 11, 4, 62, 46, 55, 26, 59, 40, 36, 15,
38 53, 34, 51, 20, 43, 31, 22, 10, 45, 25, 39, 14, 33,
39 19, 30, 9, 24, 13, 18, 8, 12, 7, 6, 5, 63 };
40
41 uint64_t t = in | (in >> 1);
42 t |= t >> 2;
43 t |= t >> 4;
44 t |= t >> 8;
45 t |= t >> 16;
46 t |= t >> 32;
47 return static_cast<uint64_t>(de_bruijn_sequence[(t * 0x03F79D71B4CB0A89ULL) >> 58ULL]);
48};
49
50template <typename T> constexpr inline T get_msb(const T in)
51{
52 return (sizeof(T) <= 4) ? get_msb32(in) : get_msb64(in);
53}
54
55constexpr inline uint32_t get_lsb32(const uint32_t in)
56{
57 if (in == 0) {
58 return 0;
59 }
60 return static_cast<uint32_t>(__builtin_ctz(in));
61}
62
63constexpr inline uint64_t get_lsb64(const uint64_t in)
64{
65 if (in == 0) {
66 return 0;
67 }
68 return static_cast<uint64_t>(__builtin_ctzll(in));
69}
70
71template <typename T> constexpr inline T get_lsb(const T in)
72{
73 return (sizeof(T) <= 4) ? get_lsb32(in) : get_lsb64(in);
74}
75
76template <typename T> constexpr inline T round_up_power_2(const T in)
77{
78 if (in == 0) {
79 return 0;
80 }
81 auto lower_bound = T(1) << get_msb(in);
82 if (lower_bound == in) {
83 return in;
84 }
85 // Overflow check: lower_bound is the highest power of 2 <= in,
86 // so lower_bound * 2 would overflow if lower_bound is already the top bit.
87 assert(lower_bound <= (std::numeric_limits<T>::max() >> 1));
88 return lower_bound * 2;
89}
90
91} // namespace bb::numeric
constexpr uint32_t get_lsb32(const uint32_t in)
Definition get_msb.hpp:55
constexpr uint64_t get_msb64(const uint64_t in)
Definition get_msb.hpp:33
constexpr T get_msb(const T in)
Definition get_msb.hpp:50
constexpr T round_up_power_2(const T in)
Definition get_msb.hpp:76
constexpr T get_lsb(const T in)
Definition get_msb.hpp:71
constexpr uint32_t get_msb32(const uint32_t in)
Definition get_msb.hpp:17
constexpr uint64_t get_lsb64(const uint64_t in)
Definition get_msb.hpp:63