barretenberg
Loading...
Searching...
No Matches
sparse_form.hpp
1#pragma once
2#include "barretenberg/common/throw_or_abort.hpp"
3#include <cstddef>
4#include <cstdint>
5#include <iostream>
6#include <vector>
7
8#include "../uint256/uint256.hpp"
9
10namespace numeric {
11
12inline std::vector<uint64_t> slice_input(const uint256_t& input, const uint64_t base, const size_t num_slices)
13{
14 uint256_t target = input;
15 std::vector<uint64_t> slices;
16 if (num_slices > 0) {
17 for (size_t i = 0; i < num_slices; ++i) {
18 slices.push_back((target % base).data[0]);
19 target /= base;
20 }
21 } else {
22 while (target > 0) {
23 slices.push_back((target % base).data[0]);
24 target /= base;
25 }
26 }
27 return slices;
28}
29
30inline std::vector<uint64_t> slice_input_using_variable_bases(const uint256_t& input,
31 const std::vector<uint64_t>& bases)
32{
33 uint256_t target = input;
34 std::vector<uint64_t> slices;
35 for (size_t i = 0; i < bases.size(); ++i) {
36 if (target >= bases[i] && i == bases.size() - 1) {
37 throw_or_abort(format("Last key slice greater than ", bases[i]));
38 }
39 slices.push_back((target % bases[i]).data[0]);
40 target /= bases[i];
41 }
42 return slices;
43}
44
45template <uint64_t base, uint64_t num_slices> constexpr std::array<uint256_t, num_slices> get_base_powers()
46{
47 std::array<uint256_t, num_slices> output{};
48 output[0] = 1;
49 for (size_t i = 1; i < num_slices; ++i) {
50 output[i] = output[i - 1] * base;
51 }
52 return output;
53}
54
55template <uint64_t base> constexpr uint256_t map_into_sparse_form(const uint64_t input)
56{
57 uint256_t out = 0UL;
58 auto converted = input;
59
60 constexpr auto base_powers = get_base_powers<base, 32>();
61 for (size_t i = 0; i < 32; ++i) {
62 uint64_t sparse_bit = ((converted >> i) & 1U);
63 if (sparse_bit) {
64 out += base_powers[i];
65 }
66 }
67 return out;
68}
69
70template <uint64_t base> constexpr uint64_t map_from_sparse_form(const uint256_t& input)
71{
72 uint256_t target = input;
73 uint64_t output = 0;
74
75 constexpr auto bases = get_base_powers<base, 32>();
76
77 for (uint64_t i = 0; i < 32; ++i) {
78 const auto& base_power = bases[static_cast<size_t>(31 - i)];
79 uint256_t prev_threshold = 0;
80 for (uint64_t j = 1; j < base + 1; ++j) {
81 const auto threshold = prev_threshold + base_power;
82 if (target < threshold) {
83 bool bit = ((j - 1) & 1);
84 if (bit) {
85 output += (1ULL << (31ULL - i));
86 }
87 if (j > 1) {
88 target -= (prev_threshold);
89 }
90 break;
91 }
92 prev_threshold = threshold;
93 }
94 }
95
96 return output;
97}
98
99template <uint64_t base, size_t num_bits> class sparse_int {
100 public:
101 sparse_int(const uint64_t input = 0)
102 : value(input)
103 {
104 for (size_t i = 0; i < num_bits; ++i) {
105 const uint64_t bit = (input >> i) & 1U;
106 limbs[i] = bit;
107 }
108 }
109 sparse_int(const sparse_int& other) noexcept = default;
110 sparse_int(sparse_int&& other) noexcept = default;
111 sparse_int& operator=(const sparse_int& other) noexcept = default;
112 sparse_int& operator=(sparse_int&& other) noexcept = default;
113 ~sparse_int() noexcept = default;
114
115 sparse_int operator+(const sparse_int& other) const
116 {
117 sparse_int result(*this);
118 for (size_t i = 0; i < num_bits - 1; ++i) {
119 result.limbs[i] += other.limbs[i];
120 if (result.limbs[i] >= base) {
121 result.limbs[i] -= base;
122 ++result.limbs[i + 1];
123 }
124 }
125 result.limbs[num_bits - 1] += other.limbs[num_bits - 1];
126 result.limbs[num_bits - 1] %= base;
127 result.value += other.value;
128 return result;
129 };
130
131 sparse_int operator+=(const sparse_int& other)
132 {
133 *this = *this + other;
134 return *this;
135 }
136
137 [[nodiscard]] uint64_t get_value() const { return value; }
138
139 [[nodiscard]] uint64_t get_sparse_value() const
140 {
141 uint64_t result = 0;
142 for (size_t i = num_bits - 1; i < num_bits; --i) {
143 result *= base;
144 result += limbs[i];
145 }
146 return result;
147 }
148
149 const std::array<uint64_t, num_bits>& get_limbs() const { return limbs; }
150
151 private:
152 std::array<uint64_t, num_bits> limbs;
153 uint64_t value;
154 uint64_t sparse_value;
155};
156
157} // namespace numeric
Definition: sparse_form.hpp:99
Definition: uint256.hpp:25
Definition: field2_declarations.hpp:6