87 static_assert(
sizeof(Block[2]) ==
sizeof(Block::values) * 2,
88 "The values in the block are not packed.");
92 const int leftover_blocks = num_blocks % num_blocks_per_iteration;
93 const int packed_blocks = num_blocks - leftover_blocks;
96 blocks + packed_blocks;
99 if (packed_blocks >= num_blocks_per_iteration) {
100 std::copy(blocks, blocks + num_blocks_per_iteration, sum);
102 for (
int i = num_blocks_per_iteration; i < packed_blocks;
103 i += num_blocks_per_iteration) {
104 for (
int j = 0; j < num_blocks_per_iteration; ++j) {
111 for (
int i = 0; i < leftover_blocks; ++i) {
123 for (
int i = 1; i < num_blocks_per_iteration; ++i) {
140 const Value* start_ptr = values.data();
141 const int size = values.size();
144 if (
size == 0)
return Value{0};
145 if (
size < 2 * block_size) {
146 return std::accumulate(start_ptr + 1, start_ptr +
size, *start_ptr);
149 if (assume_aligned_at_start) {
150 ABSL_ASSUME(
reinterpret_cast<std::uintptr_t
>(start_ptr) %
alignof(Block) ==
153 const Value* aligned_start_ptr =
154 assume_aligned_at_start ? start_ptr : AlignUp<alignof(Block)>(start_ptr);
155 const Block* blocks =
reinterpret_cast<const Block*
>(aligned_start_ptr);
156 const Value* end_ptr = start_ptr +
size;
157 const Value* aligned_end_ptr = AlignDown<alignof(Block)>(end_ptr);
158 ABSL_ASSUME(aligned_start_ptr <= aligned_end_ptr);
159 const size_t num_blocks = (aligned_end_ptr - aligned_start_ptr) / block_size;
161 reinterpret_cast<std::uintptr_t
>(aligned_end_ptr) %
alignof(Block) == 0);
163 Value leading_items_sum{};
164 if (!assume_aligned_at_start) {
165 leading_items_sum = std::accumulate(start_ptr, aligned_start_ptr, Value{});
168 AlignedBlockSum<block_size, num_blocks_per_iteration>(blocks, num_blocks);
169 Value block_sum = res.Sum();
170 return std::accumulate(aligned_end_ptr, end_ptr,
171 block_sum + leading_items_sum);