// Benchmarks for Eigen Tensor striding (subsampling views).
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0

#include <benchmark/benchmark.h>
#include <unsupported/Eigen/Tensor>

using namespace Eigen;

typedef float Scalar;

// --- Rank-2 read, outer dimension strided (inner runs stay contiguous) ---
static void BM_StrideReadOuter2D(benchmark::State& state) {
  const Index M = state.range(0);
  const Index N = state.range(1);
  const Index S = state.range(2);

  Tensor<Scalar, 2> A(M, N);
  A.setRandom();
  Eigen::array<Index, 2> strides = {1, S};  // ColMajor: dimension 0 is inner.

  Tensor<Scalar, 2> B;
  for (auto _ : state) {
    B = A.stride(strides);
    benchmark::DoNotOptimize(B.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < B.dimension(0); ++i) {
    for (Index j = 0; j < B.dimension(1); ++j) {
      if (B(i, j) != A(i, j * S)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * B.size());
}

// --- Rank-2 read, inner dimension strided (gather within inner runs) ---
static void BM_StrideReadInner2D(benchmark::State& state) {
  const Index M = state.range(0);
  const Index N = state.range(1);
  const Index S = state.range(2);

  Tensor<Scalar, 2> A(M, N);
  A.setRandom();
  Eigen::array<Index, 2> strides = {S, 1};

  Tensor<Scalar, 2> B;
  for (auto _ : state) {
    B = A.stride(strides);
    benchmark::DoNotOptimize(B.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < B.dimension(0); ++i) {
    for (Index j = 0; j < B.dimension(1); ++j) {
      if (B(i, j) != A(i * S, j)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * B.size());
}

// --- Identity striding (all strides 1, measures overhead) ---
static void BM_StrideIdentity2D(benchmark::State& state) {
  const Index M = state.range(0);
  const Index N = state.range(1);

  Tensor<Scalar, 2> A(M, N);
  A.setRandom();
  Eigen::array<Index, 2> strides = {1, 1};

  Tensor<Scalar, 2> B;
  for (auto _ : state) {
    B = A.stride(strides);
    benchmark::DoNotOptimize(B.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < B.dimension(0); ++i) {
    for (Index j = 0; j < B.dimension(1); ++j) {
      if (B(i, j) != A(i, j)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * B.size());
}

// --- Rank-3 read, all dimensions strided ---
static void BM_StrideRead3D(benchmark::State& state) {
  const Index D0 = state.range(0);
  const Index D1 = state.range(1);
  const Index D2 = state.range(2);

  Tensor<Scalar, 3> A(D0, D1, D2);
  A.setRandom();
  Eigen::array<Index, 3> strides = {2, 2, 2};

  Tensor<Scalar, 3> B;
  for (auto _ : state) {
    B = A.stride(strides);
    benchmark::DoNotOptimize(B.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < B.dimension(0); ++i) {
    for (Index j = 0; j < B.dimension(1); ++j) {
      for (Index k = 0; k < B.dimension(2); ++k) {
        if (B(i, j, k) != A(i * 2, j * 2, k * 2)) {
          state.SkipWithError("validation failed");
          return;
        }
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * B.size());
}

// --- Expression-sourced read (no raw buffer behind the striding) ---
static void BM_StrideExprInner2D(benchmark::State& state) {
  const Index M = state.range(0);
  const Index N = state.range(1);
  const Index S = state.range(2);

  Tensor<Scalar, 2> A(M, N);
  A.setRandom();
  Eigen::array<Index, 2> strides = {S, 1};

  Tensor<Scalar, 2> B;
  for (auto _ : state) {
    B = (A + A.constant(Scalar(1))).stride(strides);
    benchmark::DoNotOptimize(B.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < B.dimension(0); ++i) {
    for (Index j = 0; j < B.dimension(1); ++j) {
      if (B(i, j) != A(i * S, j) + Scalar(1)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * B.size());
}

// --- Rank-2 write through a strided destination ---
static void BM_StrideWriteOuter2D(benchmark::State& state) {
  const Index M = state.range(0);
  const Index N = state.range(1);
  const Index S = state.range(2);

  Tensor<Scalar, 2> A(M, (N + S - 1) / S);
  A.setRandom();
  Tensor<Scalar, 2> C(M, N);
  C.setZero();
  Eigen::array<Index, 2> strides = {1, S};

  for (auto _ : state) {
    C.stride(strides) = A;
    benchmark::DoNotOptimize(C.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < A.dimension(0); ++i) {
    for (Index j = 0; j < A.dimension(1); ++j) {
      if (C(i, j * S) != A(i, j)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * A.size());
}

static void BM_StrideWriteInner2D(benchmark::State& state) {
  const Index M = state.range(0);
  const Index N = state.range(1);
  const Index S = state.range(2);

  Tensor<Scalar, 2> A((M + S - 1) / S, N);
  A.setRandom();
  Tensor<Scalar, 2> C(M, N);
  C.setZero();
  Eigen::array<Index, 2> strides = {S, 1};

  for (auto _ : state) {
    C.stride(strides) = A;
    benchmark::DoNotOptimize(C.data());
    benchmark::ClobberMemory();
  }
  for (Index i = 0; i < A.dimension(0); ++i) {
    for (Index j = 0; j < A.dimension(1); ++j) {
      if (C(i * S, j) != A(i, j)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetItemsProcessed(state.iterations() * A.size());
}

// clang-format off
#define STRIDE_2D_SIZES ->ArgsProduct({{256, 1024}, {1024}, {2, 4}})
#define STRIDE_2D_PLAIN_SIZES ->Args({256, 1024})->Args({1024, 1024})
#define STRIDE_3D_SIZES ->Args({64, 64, 64})->Args({128, 128, 64})
// clang-format on

BENCHMARK(BM_StrideReadOuter2D) STRIDE_2D_SIZES;
BENCHMARK(BM_StrideReadInner2D) STRIDE_2D_SIZES;
BENCHMARK(BM_StrideIdentity2D) STRIDE_2D_PLAIN_SIZES;
BENCHMARK(BM_StrideRead3D) STRIDE_3D_SIZES;
BENCHMARK(BM_StrideExprInner2D) STRIDE_2D_SIZES;
BENCHMARK(BM_StrideWriteOuter2D) STRIDE_2D_SIZES;
BENCHMARK(BM_StrideWriteInner2D) STRIDE_2D_SIZES;
