// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2016
// Mehdi Goli    Codeplay Software Ltd.
// Ralph Potter  Codeplay Software Ltd.
// Luke Iwanski  Codeplay Software Ltd.
// Contact: <eigen@codeplay.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

#define EIGEN_TEST_NO_LONGDOUBLE
#define EIGEN_TEST_NO_COMPLEX

#define EIGEN_DEFAULT_DENSE_INDEX_TYPE int64_t
#define EIGEN_USE_SYCL
static const float error_threshold = 1e-8f;

#include "main.h"
#include <contrib/Eigen/Tensor>

using Eigen::Tensor;
struct Generator1D {
  Generator1D() {}

  float operator()(const array<Eigen::DenseIndex, 1>& coordinates) const { return coordinates[0]; }
};

template <typename DataType, int DataLayout, typename IndexType>
static void test_1D_sycl(const Eigen::SyclDevice& sycl_device) {
  IndexType sizeDim1 = 6;
  array<IndexType, 1> tensorRange = {{sizeDim1}};
  Tensor<DataType, 1, DataLayout, IndexType> vec(tensorRange);
  Tensor<DataType, 1, DataLayout, IndexType> result(tensorRange);

  const size_t tensorBuffSize = vec.size() * sizeof(DataType);
  DataType* gpu_data_vec = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
  DataType* gpu_data_result = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));

  TensorMap<Tensor<DataType, 1, DataLayout, IndexType>> gpu_vec(gpu_data_vec, tensorRange);
  TensorMap<Tensor<DataType, 1, DataLayout, IndexType>> gpu_result(gpu_data_result, tensorRange);

  sycl_device.memcpyHostToDevice(gpu_data_vec, vec.data(), tensorBuffSize);
  gpu_result.device(sycl_device) = gpu_vec.generate(Generator1D());
  sycl_device.memcpyDeviceToHost(result.data(), gpu_data_result, tensorBuffSize);

  for (IndexType i = 0; i < 6; ++i) {
    VERIFY_IS_EQUAL(result(i), i);
  }
}

struct Generator2D {
  Generator2D() {}

  float operator()(const array<Eigen::DenseIndex, 2>& coordinates) const {
    return 3 * coordinates[0] + 11 * coordinates[1];
  }
};

template <typename DataType, int DataLayout, typename IndexType>
static void test_2D_sycl(const Eigen::SyclDevice& sycl_device) {
  IndexType sizeDim1 = 5;
  IndexType sizeDim2 = 7;
  array<IndexType, 2> tensorRange = {{sizeDim1, sizeDim2}};
  Tensor<DataType, 2, DataLayout, IndexType> matrix(tensorRange);
  Tensor<DataType, 2, DataLayout, IndexType> result(tensorRange);

  const size_t tensorBuffSize = matrix.size() * sizeof(DataType);
  DataType* gpu_data_matrix = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
  DataType* gpu_data_result = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));

  TensorMap<Tensor<DataType, 2, DataLayout, IndexType>> gpu_matrix(gpu_data_matrix, tensorRange);
  TensorMap<Tensor<DataType, 2, DataLayout, IndexType>> gpu_result(gpu_data_result, tensorRange);

  sycl_device.memcpyHostToDevice(gpu_data_matrix, matrix.data(), tensorBuffSize);
  gpu_result.device(sycl_device) = gpu_matrix.generate(Generator2D());
  sycl_device.memcpyDeviceToHost(result.data(), gpu_data_result, tensorBuffSize);

  for (IndexType i = 0; i < 5; ++i) {
    for (IndexType j = 0; j < 5; ++j) {
      VERIFY_IS_EQUAL(result(i, j), 3 * i + 11 * j);
    }
  }
}

template <typename DataType, int DataLayout, typename IndexType>
static void test_gaussian_sycl(const Eigen::SyclDevice& sycl_device) {
  IndexType rows = 32;
  IndexType cols = 48;
  array<DataType, 2> means;
  means[0] = rows / 2.0f;
  means[1] = cols / 2.0f;
  array<DataType, 2> std_devs;
  std_devs[0] = 3.14f;
  std_devs[1] = 2.7f;
  internal::GaussianGenerator<DataType, Eigen::DenseIndex, 2> gaussian_gen(means, std_devs);

  array<IndexType, 2> tensorRange = {{rows, cols}};
  Tensor<DataType, 2, DataLayout, IndexType> matrix(tensorRange);
  Tensor<DataType, 2, DataLayout, IndexType> result(tensorRange);

  const size_t tensorBuffSize = matrix.size() * sizeof(DataType);
  DataType* gpu_data_matrix = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
  DataType* gpu_data_result = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));

  TensorMap<Tensor<DataType, 2, DataLayout, IndexType>> gpu_matrix(gpu_data_matrix, tensorRange);
  TensorMap<Tensor<DataType, 2, DataLayout, IndexType>> gpu_result(gpu_data_result, tensorRange);

  sycl_device.memcpyHostToDevice(gpu_data_matrix, matrix.data(), tensorBuffSize);
  gpu_result.device(sycl_device) = gpu_matrix.generate(gaussian_gen);
  sycl_device.memcpyDeviceToHost(result.data(), gpu_data_result, tensorBuffSize);

  for (IndexType i = 0; i < rows; ++i) {
    for (IndexType j = 0; j < cols; ++j) {
      DataType g_rows = powf(rows / 2.0f - i, 2) / (3.14f * 3.14f) * 0.5f;
      DataType g_cols = powf(cols / 2.0f - j, 2) / (2.7f * 2.7f) * 0.5f;
      DataType gaussian = expf(-g_rows - g_cols);
      Eigen::internal::isApprox(result(i, j), gaussian, error_threshold);
    }
  }
}

template <typename DataType, typename dev_Selector>
void sycl_generator_test_per_device(dev_Selector s) {
  QueueInterface queueInterface(s);
  auto sycl_device = Eigen::SyclDevice(&queueInterface);
  test_1D_sycl<DataType, RowMajor, int64_t>(sycl_device);
  test_1D_sycl<DataType, ColMajor, int64_t>(sycl_device);
  test_2D_sycl<DataType, RowMajor, int64_t>(sycl_device);
  test_2D_sycl<DataType, ColMajor, int64_t>(sycl_device);
  test_gaussian_sycl<DataType, RowMajor, int64_t>(sycl_device);
  test_gaussian_sycl<DataType, ColMajor, int64_t>(sycl_device);
}
EIGEN_DECLARE_TEST(tensor_generator_sycl) {
  for (const auto& device : Eigen::get_sycl_supported_devices()) {
    CALL_SUBTEST(sycl_generator_test_per_device<float>(device));
  }
}
