// 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

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

using Eigen::array;
using Eigen::SyclDevice;
using Eigen::Tensor;
using Eigen::TensorMap;

template <typename DataType, int DataLayout, typename IndexType>
static void test_broadcast_sycl_fixed(const Eigen::SyclDevice& sycl_device) {
  // BROADCAST test:
  IndexType inDim1 = 2;
  IndexType inDim2 = 3;
  IndexType inDim3 = 5;
  IndexType inDim4 = 7;
  IndexType bDim1 = 2;
  IndexType bDim2 = 3;
  IndexType bDim3 = 1;
  IndexType bDim4 = 4;
  array<IndexType, 4> in_range = {{inDim1, inDim2, inDim3, inDim4}};
  array<IndexType, 4> broadcasts = {{bDim1, bDim2, bDim3, bDim4}};
  array<IndexType, 4> out_range;  // = in_range * broadcasts
  for (size_t i = 0; i < out_range.size(); ++i) out_range[i] = in_range[i] * broadcasts[i];

  Tensor<DataType, 4, DataLayout, IndexType> input(in_range);
  Tensor<DataType, 4, DataLayout, IndexType> out(out_range);

  for (size_t i = 0; i < in_range.size(); ++i) VERIFY_IS_EQUAL(out.dimension(i), out_range[i]);

  for (IndexType i = 0; i < input.size(); ++i) input(i) = static_cast<DataType>(i);

  DataType* gpu_in_data =
      static_cast<DataType*>(sycl_device.allocate(input.dimensions().TotalSize() * sizeof(DataType)));
  DataType* gpu_out_data =
      static_cast<DataType*>(sycl_device.allocate(out.dimensions().TotalSize() * sizeof(DataType)));

  TensorMap<TensorFixedSize<DataType, Sizes<2, 3, 5, 7>, DataLayout, IndexType>> gpu_in(gpu_in_data, in_range);
  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu_out(gpu_out_data, out_range);
  sycl_device.memcpyHostToDevice(gpu_in_data, input.data(), (input.dimensions().TotalSize()) * sizeof(DataType));
  gpu_out.device(sycl_device) = gpu_in.broadcast(broadcasts);
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data, (out.dimensions().TotalSize()) * sizeof(DataType));

  for (IndexType i = 0; i < inDim1 * bDim1; ++i) {
    for (IndexType j = 0; j < inDim2 * bDim2; ++j) {
      for (IndexType k = 0; k < inDim3 * bDim3; ++k) {
        for (IndexType l = 0; l < inDim4 * bDim4; ++l) {
          VERIFY_IS_APPROX(input(i % 2, j % 3, k % 5, l % 7), out(i, j, k, l));
        }
      }
    }
  }
  printf("Broadcast Test with fixed size Passed\n");
  sycl_device.deallocate(gpu_in_data);
  sycl_device.deallocate(gpu_out_data);
}

template <typename DataType, int DataLayout, typename IndexType>
static void test_broadcast_sycl(const Eigen::SyclDevice& sycl_device) {
  // BROADCAST test:
  IndexType inDim1 = 2;
  IndexType inDim2 = 3;
  IndexType inDim3 = 5;
  IndexType inDim4 = 7;
  IndexType bDim1 = 2;
  IndexType bDim2 = 3;
  IndexType bDim3 = 1;
  IndexType bDim4 = 4;
  array<IndexType, 4> in_range = {{inDim1, inDim2, inDim3, inDim4}};
  array<IndexType, 4> broadcasts = {{bDim1, bDim2, bDim3, bDim4}};
  array<IndexType, 4> out_range;  // = in_range * broadcasts
  for (size_t i = 0; i < out_range.size(); ++i) out_range[i] = in_range[i] * broadcasts[i];

  Tensor<DataType, 4, DataLayout, IndexType> input(in_range);
  Tensor<DataType, 4, DataLayout, IndexType> out(out_range);

  for (size_t i = 0; i < in_range.size(); ++i) VERIFY_IS_EQUAL(out.dimension(i), out_range[i]);

  for (IndexType i = 0; i < input.size(); ++i) input(i) = static_cast<DataType>(i);

  DataType* gpu_in_data =
      static_cast<DataType*>(sycl_device.allocate(input.dimensions().TotalSize() * sizeof(DataType)));
  DataType* gpu_out_data =
      static_cast<DataType*>(sycl_device.allocate(out.dimensions().TotalSize() * sizeof(DataType)));

  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu_in(gpu_in_data, in_range);
  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu_out(gpu_out_data, out_range);
  sycl_device.memcpyHostToDevice(gpu_in_data, input.data(), (input.dimensions().TotalSize()) * sizeof(DataType));
  gpu_out.device(sycl_device) = gpu_in.broadcast(broadcasts);
  sycl_device.memcpyDeviceToHost(out.data(), gpu_out_data, (out.dimensions().TotalSize()) * sizeof(DataType));

  for (IndexType i = 0; i < inDim1 * bDim1; ++i) {
    for (IndexType j = 0; j < inDim2 * bDim2; ++j) {
      for (IndexType k = 0; k < inDim3 * bDim3; ++k) {
        for (IndexType l = 0; l < inDim4 * bDim4; ++l) {
          VERIFY_IS_APPROX(input(i % inDim1, j % inDim2, k % inDim3, l % inDim4), out(i, j, k, l));
        }
      }
    }
  }
  printf("Broadcast Test Passed\n");
  sycl_device.deallocate(gpu_in_data);
  sycl_device.deallocate(gpu_out_data);
}

template <typename DataType>
void sycl_broadcast_test_per_device(const cl::sycl::device& d) {
  std::cout << "Running on " << d.template get_info<cl::sycl::info::device::name>() << std::endl;
  QueueInterface queueInterface(d);
  auto sycl_device = Eigen::SyclDevice(&queueInterface);
  test_broadcast_sycl<DataType, RowMajor, int64_t>(sycl_device);
  test_broadcast_sycl<DataType, ColMajor, int64_t>(sycl_device);
  test_broadcast_sycl_fixed<DataType, RowMajor, int64_t>(sycl_device);
  test_broadcast_sycl_fixed<DataType, ColMajor, int64_t>(sycl_device);
}

EIGEN_DECLARE_TEST(tensor_broadcast_sycl) {
  for (const auto& device : Eigen::get_sycl_supported_devices()) {
    CALL_SUBTEST(sycl_broadcast_test_per_device<half>(device));
    CALL_SUBTEST(sycl_broadcast_test_per_device<float>(device));
  }
}
