Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
accumulator.hpp
Go to the documentation of this file.
1#pragma once
2
5
6#include <array>
7#include <cstddef>
8
9namespace bb {
10
11// Per-token reduction accumulator for use inside `vectorized_for<N>` kernels.
12//
13// Pairs with Polynomial / PolynomialSpan's token-dispatched operator[] to
14// keep the kernel body uniform across the bulk and tail paths. The bulk
15// (ContiguousVectorIndex<N>) contributions land in a VectorField slot,
16// summing lane-wise; the tail (ScalarIndex) contributions land in a scalar
17// Fr slot. `reduce()` horizontal-adds the N lanes together with the scalar
18// to give the final result.
19//
20// Canonical kernel shape:
21//
22// Accumulator<Fr> acc;
23// vectorized_for<VECTOR_FIELD_WIDTH>(0, n, [&](auto ctx) {
24// acc += view[ctx]; // dot, sum, …
25// });
26// Fr result = acc.reduce();
27//
28// Both forms — `scalar_acc` and `vector_acc` — are materialised in the
29// constructor so the loop never branches on the token type to pick an
30// accumulator. The compile-time branch lives at the operator+= overload
31// set: ScalarIndex iterations hit operator+=(const Fr&), bulk iterations
32// hit operator+=(const Vec&).
33//
34// Reduction order is implementation-defined: lanes are summed in lane
35// order (L=0,1,2,3,4) then added to the scalar slot. For finite field
36// addition this is associative and commutative so the result is bit-
37// identical regardless, but callers that care about specific summation
38// order for floats / Kahan-style work should not use this.
39template <typename Fr> struct Accumulator {
41
44
46 : scalar_acc(0)
47 , vector_acc(Vec::broadcast(Fr(0)))
48 {}
49
50 [[gnu::always_inline]] void operator+=(const Fr& v) { scalar_acc = scalar_acc + v; }
51
52 [[gnu::always_inline]] void operator+=(const Vec& v) { vector_acc = vector_acc + v; }
53
54 // Horizontal reduce: sum all lanes of vector_acc and the scalar slot
55 // into a single Fr. Tree-shaped (depth 3 for 6 inputs) so a chain of
56 // five serial Fr-adds does not sit on the critical path.
57 Fr reduce() const
58 {
59 static_assert(VECTOR_FIELD_WIDTH == 5, "Accumulator::reduce tree assumes width 5");
61 const Fr s01 = lanes[0] + lanes[1];
62 const Fr s23 = lanes[2] + lanes[3];
63 const Fr s4s = lanes[4] + scalar_acc;
64 return (s01 + s23) + s4s;
65 }
66};
67
68} // namespace bb
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr size_t VECTOR_FIELD_WIDTH
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Fr reduce() const
void operator+=(const Fr &v)
void operator+=(const Vec &v)
std::array< Field, 5 > to_array() const noexcept