// Benchmarks for Eigen Tensor broadcasting.
// Tests broadcasting along various dimensions and ranks.
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0

#define EIGEN_USE_THREADS

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

using namespace Eigen;

typedef float Scalar;

// --- Broadcast row vector {1,N} -> {M,N} ---
static void BM_BroadcastRow(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);

  Tensor<Scalar, 2> row(1, N);
  Tensor<Scalar, 2> result(M, N);
  row.setRandom();

  Eigen::array<int, 2> bcast = {M, 1};

  for (auto _ : state) {
    result = row.broadcast(bcast);
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar));
}

// --- Broadcast col vector {M,1} -> {M,N} ---
static void BM_BroadcastCol(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);

  Tensor<Scalar, 2> col(M, 1);
  Tensor<Scalar, 2> result(M, N);
  col.setRandom();

  Eigen::array<int, 2> bcast = {1, N};

  for (auto _ : state) {
    result = col.broadcast(bcast);
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar));
}

// --- Broadcast + element-wise add (bias addition pattern) ---
static void BM_BroadcastAdd(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);

  Tensor<Scalar, 2> mat(M, N);
  Tensor<Scalar, 2> bias(1, N);
  Tensor<Scalar, 2> result(M, N);
  mat.setRandom();
  bias.setRandom();

  Eigen::array<int, 2> bcast = {M, 1};

  for (auto _ : state) {
    result = mat + bias.broadcast(bcast);
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar) * 2);
}

// --- Broadcast + scalar clamp (bias addition + clamp pattern) ---
// cwiseMax(Scalar) / cwiseMin(Scalar) build constant() leaves (unlike
// clip(), which is a single unary functor). Constants used to disable tiled
// evaluation for the whole expression.
static void BM_BroadcastClamp(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);

  Tensor<Scalar, 2> mat(M, N);
  Tensor<Scalar, 2> bias(1, N);
  Tensor<Scalar, 2> result(M, N);
  mat.setRandom();
  bias.setRandom();

  Eigen::array<int, 2> bcast = {M, 1};

  for (auto _ : state) {
    result = (mat + bias.broadcast(bcast)).cwiseMax(Scalar(-0.5)).cwiseMin(Scalar(0.5));
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }

  // Validate outside the timed loop.
  for (int i = 0; i < M; ++i) {
    for (int j = 0; j < N; ++j) {
      const Scalar expected = std::min(Scalar(0.5), std::max(Scalar(-0.5), mat(i, j) + bias(0, j)));
      if (result(i, j) != expected) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar) * 2);
}

// --- Outer-dimension broadcast + clip ---
// Broadcasting a large plane along the outer-most dimension has a reuse
// distance of the whole plane: the untiled path streams the plane from
// memory B times, while tiled evaluation reuses cache-resident pieces
// across the broadcast factor. The cwiseMax/cwiseMin constants decide
// which of the two paths runs, so before nullary block support they forced
// the memory-bound path.
static void BM_OuterBroadcastClamp(benchmark::State& state) {
  const int D0 = state.range(0);
  const int D1 = state.range(1);
  const int B = state.range(2);

  Tensor<Scalar, 3> plane(D0, D1, 1);
  Tensor<Scalar, 3> result(D0, D1, B);
  plane.setRandom();

  Eigen::array<int, 3> bcast = {1, 1, B};

  for (auto _ : state) {
    result = plane.broadcast(bcast).cwiseMax(Scalar(-0.5)).cwiseMin(Scalar(0.5));
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }

  for (int i = 0; i < D0; ++i) {
    for (int j = 0; j < D1; ++j) {
      const Scalar expected = std::min(Scalar(0.5), std::max(Scalar(-0.5), plane(i, j, 0)));
      for (int k = 0; k < B; ++k) {
        if (result(i, j, k) != expected) {
          state.SkipWithError("validation failed");
          return;
        }
      }
    }
  }
  state.SetBytesProcessed(state.iterations() * D0 * D1 * B * sizeof(Scalar));
}

// --- Transpose (shuffle) + scalar clamp ---
// A shuffled inner dimension makes the linear path a per-element gather with
// a full index-remapping walk, while the block path runs a cache-blocked
// transpose through TensorBlockIO. The cwiseMax/cwiseMin constants decide
// which path runs, so before nullary block support they forced the gather.
static void BM_ShuffleClamp(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);

  Tensor<Scalar, 2> mat(M, N);
  Tensor<Scalar, 2> result(N, M);
  mat.setRandom();

  Eigen::array<int, 2> transpose = {1, 0};

  for (auto _ : state) {
    result = mat.shuffle(transpose).cwiseMax(Scalar(-0.5)).cwiseMin(Scalar(0.5));
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }

  for (int i = 0; i < N; ++i) {
    for (int j = 0; j < M; ++j) {
      const Scalar expected = std::min(Scalar(0.5), std::max(Scalar(-0.5), mat(j, i)));
      if (result(i, j) != expected) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar));
}

// --- Pad + scalar clamp (convolution-style padding + clamp) ---
static void BM_PadClamp(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);
  const int P = state.range(2);

  Tensor<Scalar, 2> mat(M, N);
  Tensor<Scalar, 2> result(M + 2 * P, N + 2 * P);
  mat.setRandom();

  Eigen::array<std::pair<int, int>, 2> paddings;
  paddings[0] = {P, P};
  paddings[1] = {P, P};

  for (auto _ : state) {
    result = mat.pad(paddings).cwiseMax(Scalar(-0.5)).cwiseMin(Scalar(0.5));
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }

  for (int i = 0; i < M + 2 * P; ++i) {
    for (int j = 0; j < N + 2 * P; ++j) {
      const bool interior = i >= P && i < M + P && j >= P && j < N + P;
      const Scalar padded = interior ? mat(i - P, j - P) : Scalar(0);
      const Scalar expected = std::min(Scalar(0.5), std::max(Scalar(-0.5), padded));
      if (result(i, j) != expected) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetBytesProcessed(state.iterations() * (M + 2 * P) * (N + 2 * P) * sizeof(Scalar));
}

// --- Constant multiply without any block-preferring node (control) ---
// No node prefers block access here, so this expression stays on the linear
// vectorized path; it pins that nullary block support does not change it.
static void BM_ConstantMul(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);

  Tensor<Scalar, 2> mat(M, N);
  Tensor<Scalar, 2> result(M, N);
  mat.setRandom();

  for (auto _ : state) {
    result = mat * mat.constant(Scalar(3));
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }

  for (int i = 0; i < M; ++i) {
    for (int j = 0; j < N; ++j) {
      if (result(i, j) != Scalar(3) * mat(i, j)) {
        state.SkipWithError("validation failed");
        return;
      }
    }
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar) * 2);
}

// --- Rank-4 broadcast (batch x channels x 1 x 1) -> (batch x channels x H x W) ---
static void BM_BroadcastRank4(benchmark::State& state) {
  const int batch = state.range(0);
  const int C = state.range(1);
  const int H = state.range(2);

  Tensor<Scalar, 4> bias(batch, C, 1, 1);
  Tensor<Scalar, 4> result(batch, C, H, H);
  bias.setRandom();

  Eigen::array<int, 4> bcast = {1, 1, H, H};

  for (auto _ : state) {
    result = bias.broadcast(bcast);
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }
  state.SetBytesProcessed(state.iterations() * batch * C * H * H * sizeof(Scalar));
}

// --- ThreadPool variants ---

static void BM_BroadcastRow_ThreadPool(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);
  const int threads = state.range(2);

  Tensor<Scalar, 2> row(1, N);
  Tensor<Scalar, 2> result(M, N);
  row.setRandom();

  ThreadPool tp(threads);
  ThreadPoolDevice dev(&tp, threads);

  Eigen::array<int, 2> bcast = {M, 1};

  for (auto _ : state) {
    result.device(dev) = row.broadcast(bcast);
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar));
  state.counters["threads"] = threads;
}

static void BM_BroadcastAdd_ThreadPool(benchmark::State& state) {
  const int M = state.range(0);
  const int N = state.range(1);
  const int threads = state.range(2);

  Tensor<Scalar, 2> mat(M, N);
  Tensor<Scalar, 2> bias(1, N);
  Tensor<Scalar, 2> result(M, N);
  mat.setRandom();
  bias.setRandom();

  ThreadPool tp(threads);
  ThreadPoolDevice dev(&tp, threads);

  Eigen::array<int, 2> bcast = {M, 1};

  for (auto _ : state) {
    result.device(dev) = mat + bias.broadcast(bcast);
    benchmark::DoNotOptimize(result.data());
    benchmark::ClobberMemory();
  }
  state.SetBytesProcessed(state.iterations() * M * N * sizeof(Scalar) * 2);
  state.counters["threads"] = threads;
}

// {m, n} and {batch, c, h}: pure Cartesian products.
#define BROADCAST_SIZES ->ArgsProduct({{64, 256, 1024}, {64, 256, 1024}})
#define BROADCAST_RANK4_SIZES ->ArgsProduct({{1, 8}, {64, 256}, {16, 32}})

// {size, size, threads}: explicit because size is repeated.
// clang-format off
#define BROADCAST_THREADPOOL_SIZES \
  ->Args({256, 256, 1})->Args({256, 256, 2})->Args({256, 256, 4}) \
  ->Args({256, 256, 8})->Args({256, 256, 12})->Args({256, 256, 16}) \
  ->Args({1024, 1024, 1})->Args({1024, 1024, 2})->Args({1024, 1024, 4}) \
  ->Args({1024, 1024, 8})->Args({1024, 1024, 12})->Args({1024, 1024, 16})
// clang-format on

BENCHMARK(BM_BroadcastRow) BROADCAST_SIZES;
BENCHMARK(BM_BroadcastCol) BROADCAST_SIZES;
BENCHMARK(BM_BroadcastAdd) BROADCAST_SIZES;
BENCHMARK(BM_BroadcastClamp) BROADCAST_SIZES;
BENCHMARK(BM_OuterBroadcastClamp)->ArgsProduct({{512, 1024}, {512, 1024}, {8}});
BENCHMARK(BM_ShuffleClamp)->ArgsProduct({{256, 1024, 4096}, {256, 1024, 4096}});
BENCHMARK(BM_PadClamp)->ArgsProduct({{256, 1024}, {256, 1024}, {1, 4}});
BENCHMARK(BM_ConstantMul) BROADCAST_SIZES;
BENCHMARK(BM_BroadcastRank4) BROADCAST_RANK4_SIZES;
BENCHMARK(BM_BroadcastRow_ThreadPool) BROADCAST_THREADPOOL_SIZES->UseRealTime();
BENCHMARK(BM_BroadcastAdd_ThreadPool) BROADCAST_THREADPOOL_SIZES->UseRealTime();
