19inline std::array<Field, W>
compute_lane_inverses(
const std::array<Field, W>& acc_lanes, Field running_inv)
noexcept
22 std::array<Field, W> prefix;
23 prefix[0] = acc_lanes[0];
24 for (
size_t k = 1; k < W - 1; ++k) {
25 prefix[k] = prefix[k - 1] * acc_lanes[k];
27 std::array<Field, W> inv_lanes;
28 for (
size_t k = W; k-- > 1;) {
29 inv_lanes[k] = running_inv * prefix[k - 1];
30 running_inv = running_inv * acc_lanes[k];
32 inv_lanes[0] = running_inv;
62 auto [acc, tail_acc] = map_accumulate<Direction::Forward>(
63 in,
out,
Vec::broadcast(Field::one()), Field::one(), [](
auto&
a,
const auto& in_e,
auto& out_e) {
69 const std::array<Field, W> acc_lanes = acc.to_array();
70 Field bulk_product = acc_lanes[0];
71 for (
size_t j = 1; j < W; ++j) {
72 bulk_product = bulk_product * acc_lanes[j];
74 const Field total = bulk_product * tail_acc;
75 if (total.is_zero()) {
78 const Field inv_total = total.invert();
79 const Field inv_bulk_product = inv_total * tail_acc;
80 const Field inv_tail_acc = inv_total * bulk_product;
81 const std::array<Field, W> lane_inv = compute_lane_inverses<Field, W>(acc_lanes, inv_bulk_product);
84 map_accumulate<Direction::Backward>(
85 in,
out,
Vec(lane_inv), inv_tail_acc, [](
auto& state,
const auto& in_e,
auto& out_e) {
86 out_e = state * out_e;