// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "benchmark/benchmark.h"

#include <vector>

#include "arrow/compute/api_scalar.h"
#include "arrow/compute/kernels/test_util.h"
#include "arrow/testing/gtest_util.h"
#include "arrow/testing/random.h"
#include "arrow/util/benchmark_util.h"

namespace arrow {
namespace compute {

constexpr auto kSeed = 0x94378165;

using BinaryOp = Result<Datum>(const Datum&, const Datum&, ArithmeticOptions,
                               ExecContext*);

// Add explicit overflow-checked shortcuts, for easy benchmark parametering.
static Result<Datum> AddChecked(const Datum& left, const Datum& right,
                                ArithmeticOptions options = ArithmeticOptions(),
                                ExecContext* ctx = NULLPTR) {
  options.check_overflow = true;
  return Add(left, right, std::move(options), ctx);
}

static Result<Datum> SubtractChecked(const Datum& left, const Datum& right,
                                     ArithmeticOptions options = ArithmeticOptions(),
                                     ExecContext* ctx = NULLPTR) {
  options.check_overflow = true;
  return Subtract(left, right, std::move(options), ctx);
}

static Result<Datum> MultiplyChecked(const Datum& left, const Datum& right,
                                     ArithmeticOptions options = ArithmeticOptions(),
                                     ExecContext* ctx = NULLPTR) {
  options.check_overflow = true;
  return Multiply(left, right, std::move(options), ctx);
}

static Result<Datum> DivideChecked(const Datum& left, const Datum& right,
                                   ArithmeticOptions options = ArithmeticOptions(),
                                   ExecContext* ctx = NULLPTR) {
  options.check_overflow = true;
  return Divide(left, right, std::move(options), ctx);
}

template <BinaryOp& Op, typename ArrowType, typename CType = typename ArrowType::c_type>
static void ArrayScalarKernel(benchmark::State& state) {
  RegressionArgs args(state);

  const int64_t array_size = args.size / sizeof(CType);

  // Choose values so as to avoid overflow on all ops and types
  auto min = static_cast<CType>(6);
  auto max = static_cast<CType>(min + 15);
  Datum rhs(static_cast<CType>(6));

  auto rand = random::RandomArrayGenerator(kSeed);
  auto lhs = std::static_pointer_cast<NumericArray<ArrowType>>(
      rand.Numeric<ArrowType>(array_size, min, max, args.null_proportion));

  for (auto _ : state) {
    ABORT_NOT_OK(Op(lhs, rhs, ArithmeticOptions(), nullptr).status());
  }
  state.SetItemsProcessed(state.iterations() * array_size);
}

template <BinaryOp& Op, typename ArrowType, typename CType = typename ArrowType::c_type>
static void ArrayArrayKernel(benchmark::State& state) {
  RegressionArgs args(state);

  // Choose values so as to avoid overflow on all ops and types
  const int64_t array_size = args.size / sizeof(CType);
  auto rmin = static_cast<CType>(1);
  auto rmax = static_cast<CType>(rmin + 6);  // 7
  auto lmin = static_cast<CType>(rmax + 1);  // 8
  auto lmax = static_cast<CType>(lmin + 6);  // 14

  auto rand = random::RandomArrayGenerator(kSeed);
  auto lhs = std::static_pointer_cast<NumericArray<ArrowType>>(
      rand.Numeric<ArrowType>(array_size, lmin, lmax, args.null_proportion));
  auto rhs = std::static_pointer_cast<NumericArray<ArrowType>>(
      rand.Numeric<ArrowType>(array_size, rmin, rmax, args.null_proportion));

  for (auto _ : state) {
    ABORT_NOT_OK(Op(lhs, rhs, ArithmeticOptions(), nullptr).status());
  }
  state.SetItemsProcessed(state.iterations() * array_size);
}

void SetArgs(benchmark::internal::Benchmark* bench) {
  for (const auto inverse_null_proportion : std::vector<ArgsType>({100, 0})) {
    bench->Args({static_cast<ArgsType>(kL2Size), inverse_null_proportion});
  }
}

#define DECLARE_ARITHMETIC_BENCHMARKS(BENCHMARK, OP)             \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int64Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int32Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int16Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int8Type)->Apply(SetArgs);   \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt64Type)->Apply(SetArgs); \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt32Type)->Apply(SetArgs); \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt16Type)->Apply(SetArgs); \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt8Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, FloatType)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, DoubleType)->Apply(SetArgs)

// Checked floating-point variants of arithmetic operations are identical to
// non-checked variants, so do not bother measuring them.

#define DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(BENCHMARK, OP)     \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int64Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int32Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int16Type)->Apply(SetArgs);  \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, Int8Type)->Apply(SetArgs);   \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt64Type)->Apply(SetArgs); \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt32Type)->Apply(SetArgs); \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt16Type)->Apply(SetArgs); \
  BENCHMARK_TEMPLATE(BENCHMARK, OP, UInt8Type)->Apply(SetArgs);

DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Add);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Add);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Subtract);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Subtract);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Multiply);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Multiply);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayArrayKernel, Divide);
DECLARE_ARITHMETIC_BENCHMARKS(ArrayScalarKernel, Divide);

DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, AddChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, AddChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, SubtractChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, SubtractChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, MultiplyChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, MultiplyChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayArrayKernel, DivideChecked);
DECLARE_ARITHMETIC_CHECKED_BENCHMARKS(ArrayScalarKernel, DivideChecked);

}  // namespace compute
}  // namespace arrow
