Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
straus_scalar_slice.cpp
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
8#include "./cycle_scalar.hpp"
12
13namespace bb::stdlib {
14
27template <typename Builder>
29 Builder* context, const field_t& scalar, const size_t num_bits, const size_t table_bits)
30{
32 const size_t num_slices = numeric::ceil_div(num_bits, table_bits);
33
34 // We record the scalar slices both as field_t circuit elements and u64 values. (u64 values are used to index
35 // arrays and we don't want to repeatedly cast a stdlib value to a numeric primitive as this gets expensive when
36 // done repeatedly)
37 std::vector<field_ct> stdlib_slices;
38 std::vector<uint64_t> native_slices;
39 stdlib_slices.reserve(num_slices);
40 native_slices.reserve(num_slices);
41
42 if (num_bits == 0) {
43 return { stdlib_slices, native_slices };
44 }
45 // Case 1: If the scalar is constant, compute the slices natively
46 if (scalar.is_constant()) {
47 const uint64_t table_mask = (1ULL << table_bits) - 1ULL;
48 uint256_t raw_value = scalar.get_value();
49 for (size_t i = 0; i < num_slices; ++i) {
50 uint64_t slice_value = static_cast<uint64_t>(raw_value.data[0]) & table_mask;
51 stdlib_slices.push_back(field_ct(slice_value)); // constants equal to slice_value
52 native_slices.push_back(slice_value);
53 raw_value = raw_value >> table_bits;
54 }
55 return { stdlib_slices, native_slices };
56 }
57
58 // Case 2: If the scalar is non-constant, perform the decomposition in-circuit
59 const auto slice_indices =
60 context->decompose_into_default_range(scalar.get_normalized_witness_index(),
61 num_bits,
62 table_bits,
63 "straus_scalar_slice decompose_into_default_range");
64 for (auto const& idx : slice_indices) {
66 stdlib_slices.push_back(slice);
67 native_slices.push_back(static_cast<uint64_t>(slice.get_value()));
68 }
69 return { stdlib_slices, native_slices };
70}
71
81template <typename Builder>
83 const cycle_scalar<Builder>& scalar,
84 const size_t table_bits)
85 : _table_bits(table_bits)
86{
87 constexpr size_t LO_BITS = cycle_scalar<Builder>::LO_BITS;
88 const size_t lo_bits = scalar.num_bits() > LO_BITS ? LO_BITS : scalar.num_bits();
89 const size_t hi_bits = scalar.num_bits() > LO_BITS ? scalar.num_bits() - LO_BITS : 0;
90 auto hi_slices = compute_scalar_slices(context, scalar.hi, hi_bits, table_bits);
91 auto lo_slices = compute_scalar_slices(context, scalar.lo, lo_bits, table_bits);
92
93 std::copy(lo_slices.first.begin(), lo_slices.first.end(), std::back_inserter(slices));
94 std::copy(hi_slices.first.begin(), hi_slices.first.end(), std::back_inserter(slices));
95 std::copy(lo_slices.second.begin(), lo_slices.second.end(), std::back_inserter(slices_native));
96 std::copy(hi_slices.second.begin(), hi_slices.second.end(), std::back_inserter(slices_native));
97
98 const auto tag = scalar.get_origin_tag();
99 for (auto& element : slices) {
100 // All slices need to have the same origin tag
101 element.set_origin_tag(tag);
102 }
103}
104
114template <typename Builder> field_t<Builder> straus_scalar_slices<Builder>::operator[](size_t index)
115{
116 BB_ASSERT_LT(index, slices.size(), "Straus scalar slice index out of bounds!");
117 return slices[index];
118}
119
122
123} // namespace bb::stdlib
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:148
Represents a member of the Grumpkin curve scalar field (i.e. BN254 base field).
OriginTag get_origin_tag() const
Get the origin tag of the cycle_scalar (a merge of the lo and hi tags)
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:61
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:829
bool is_constant() const
Definition field.hpp:407
uint32_t get_normalized_witness_index() const
Get the index of a normalized version of this element.
Definition field.hpp:479
straus_scalar_slices decomposes an input scalar into bit-slices of size table_bits....
static std::pair< std::vector< field_t >, std::vector< uint64_t > > compute_scalar_slices(Builder *context, const field_t &scalar, size_t num_bits, size_t table_bits)
Convert an input cycle_scalar field element into a vector of bit-slices.
field_t operator[](size_t index)
Return a bit-slice associated with round index.
straus_scalar_slices(Builder *context, const cycle_scalar< Builder > &scalars, size_t table_bits)
Construct straus_scalar_slices from an input cycle_scalar and specified table_bits.
StrictMock< MockContext > context
stdlib::field_t< Builder > field_ct
constexpr T ceil_div(const T &numerator, const T &denominator)
Computes the ceiling of the division of two integral types.
Definition general.hpp:23
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
C slice(C const &container, size_t start)
Definition container.hpp:9
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13