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