15#include <benchmark/benchmark.h>
18using namespace benchmark;
23constexpr size_t N = 1 << 16;
41 for (
size_t i = 0; i <
N; ++i) {
48 void reset_self(State& state)
59struct CorrectnessGuard {
62 constexpr size_t M =
N;
66 for (
size_t i = 0; i < M; ++i) {
72 auto check = [&](
const char*
label) {
73 for (
size_t i = 0; i < M; ++i) {
74 if (!(
a.at(i) == a_ref.
at(i))) {
84 for (
size_t i = 0; i < M; ++i) {
85 a_ref.
at(i) = a_ref.
at(i) +
b.at(i);
92 for (
size_t i = 0; i < M; ++i) {
93 a_ref.
at(i) = a_ref.
at(i) -
b.at(i);
100 for (
size_t i = 0; i < M; ++i) {
101 a_ref.
at(i) = a_ref.
at(i) * s;
106static const CorrectnessGuard correctness_guard;
112static void bench_plus_equals_scalar(State& state)
116 auto& other = f.other;
117 for (
auto _ : state) {
119 for (
size_t i = 0; i <
N; ++i) {
120 self.at(i) = self.at(i) + other.at(i);
122 DoNotOptimize(self.at(0));
127static void bench_plus_equals_full(State& state)
131 auto& other = f.other;
132 for (
auto _ : state) {
135 DoNotOptimize(self.at(0));
142static void bench_minus_equals_scalar(State& state)
146 auto& other = f.other;
147 for (
auto _ : state) {
149 for (
size_t i = 0; i <
N; ++i) {
150 self.at(i) = self.at(i) - other.at(i);
152 DoNotOptimize(self.at(0));
157static void bench_minus_equals_full(State& state)
161 auto& other = f.other;
162 for (
auto _ : state) {
165 DoNotOptimize(self.at(0));
172static void bench_times_equals_scalar(State& state)
176 auto scaling = f.scaling;
177 for (
auto _ : state) {
179 for (
size_t i = 0; i <
N; ++i) {
180 self.at(i) = self.at(i) * scaling;
182 DoNotOptimize(self.at(0));
187static void bench_times_equals_full(State& state)
191 auto scaling = f.scaling;
192 for (
auto _ : state) {
195 DoNotOptimize(self.at(0));
Fr & at(size_t index)
Our mutable accessor, unlike operator[]. We abuse precedent a bit to differentiate at() and operator[...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
BENCHMARK(bench_plus_equals_scalar)
static field random_element(numeric::RNG *engine=nullptr) noexcept