// 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::Tensor;

// Inflation Definition for each dimension the inflated val would be
//((dim-1)*strid[dim] +1)

// for 1 dimension vector of size 3 with value (4,4,4) with the inflated stride value of 3 would be changed to
// tensor of size (2*3) +1 = 7 with the value of
// (4, 0, 0, 4, 0, 0, 4).

template <typename DataType, int DataLayout, typename IndexType>
void test_simple_inflation_sycl(const Eigen::SyclDevice& sycl_device) {
  IndexType sizeDim1 = 2;
  IndexType sizeDim2 = 3;
  IndexType sizeDim3 = 5;
  IndexType sizeDim4 = 7;
  array<IndexType, 4> tensorRange = {{sizeDim1, sizeDim2, sizeDim3, sizeDim4}};
  Tensor<DataType, 4, DataLayout, IndexType> tensor(tensorRange);
  Tensor<DataType, 4, DataLayout, IndexType> no_stride(tensorRange);
  tensor.setRandom();

  array<IndexType, 4> strides;
  strides[0] = 1;
  strides[1] = 1;
  strides[2] = 1;
  strides[3] = 1;

  const size_t tensorBuffSize = tensor.size() * sizeof(DataType);
  DataType* gpu_data_tensor = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));
  DataType* gpu_data_no_stride = static_cast<DataType*>(sycl_device.allocate(tensorBuffSize));

  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu_tensor(gpu_data_tensor, tensorRange);
  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu_no_stride(gpu_data_no_stride, tensorRange);

  sycl_device.memcpyHostToDevice(gpu_data_tensor, tensor.data(), tensorBuffSize);
  gpu_no_stride.device(sycl_device) = gpu_tensor.inflate(strides);
  sycl_device.memcpyDeviceToHost(no_stride.data(), gpu_data_no_stride, tensorBuffSize);

  VERIFY_IS_EQUAL(no_stride.dimension(0), sizeDim1);
  VERIFY_IS_EQUAL(no_stride.dimension(1), sizeDim2);
  VERIFY_IS_EQUAL(no_stride.dimension(2), sizeDim3);
  VERIFY_IS_EQUAL(no_stride.dimension(3), sizeDim4);

  for (IndexType i = 0; i < 2; ++i) {
    for (IndexType j = 0; j < 3; ++j) {
      for (IndexType k = 0; k < 5; ++k) {
        for (IndexType l = 0; l < 7; ++l) {
          VERIFY_IS_EQUAL(tensor(i, j, k, l), no_stride(i, j, k, l));
        }
      }
    }
  }

  strides[0] = 2;
  strides[1] = 4;
  strides[2] = 2;
  strides[3] = 3;

  IndexType inflatedSizeDim1 = 3;
  IndexType inflatedSizeDim2 = 9;
  IndexType inflatedSizeDim3 = 9;
  IndexType inflatedSizeDim4 = 19;
  array<IndexType, 4> inflatedTensorRange = {{inflatedSizeDim1, inflatedSizeDim2, inflatedSizeDim3, inflatedSizeDim4}};

  Tensor<DataType, 4, DataLayout, IndexType> inflated(inflatedTensorRange);

  const size_t inflatedTensorBuffSize = inflated.size() * sizeof(DataType);
  DataType* gpu_data_inflated = static_cast<DataType*>(sycl_device.allocate(inflatedTensorBuffSize));
  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu_inflated(gpu_data_inflated, inflatedTensorRange);
  gpu_inflated.device(sycl_device) = gpu_tensor.inflate(strides);
  sycl_device.memcpyDeviceToHost(inflated.data(), gpu_data_inflated, inflatedTensorBuffSize);

  VERIFY_IS_EQUAL(inflated.dimension(0), inflatedSizeDim1);
  VERIFY_IS_EQUAL(inflated.dimension(1), inflatedSizeDim2);
  VERIFY_IS_EQUAL(inflated.dimension(2), inflatedSizeDim3);
  VERIFY_IS_EQUAL(inflated.dimension(3), inflatedSizeDim4);

  for (IndexType i = 0; i < inflatedSizeDim1; ++i) {
    for (IndexType j = 0; j < inflatedSizeDim2; ++j) {
      for (IndexType k = 0; k < inflatedSizeDim3; ++k) {
        for (IndexType l = 0; l < inflatedSizeDim4; ++l) {
          if (i % strides[0] == 0 && j % strides[1] == 0 && k % strides[2] == 0 && l % strides[3] == 0) {
            VERIFY_IS_EQUAL(inflated(i, j, k, l),
                            tensor(i / strides[0], j / strides[1], k / strides[2], l / strides[3]));
          } else {
            VERIFY_IS_EQUAL(0, inflated(i, j, k, l));
          }
        }
      }
    }
  }
  sycl_device.deallocate(gpu_data_tensor);
  sycl_device.deallocate(gpu_data_no_stride);
  sycl_device.deallocate(gpu_data_inflated);
}

template <typename DataType, typename dev_Selector>
void sycl_inflation_test_per_device(dev_Selector s) {
  QueueInterface queueInterface(s);
  auto sycl_device = Eigen::SyclDevice(&queueInterface);
  test_simple_inflation_sycl<DataType, RowMajor, int64_t>(sycl_device);
  test_simple_inflation_sycl<DataType, ColMajor, int64_t>(sycl_device);
}
EIGEN_DECLARE_TEST(tensor_inflation_sycl) {
  for (const auto& device : Eigen::get_sycl_supported_devices()) {
    CALL_SUBTEST(sycl_inflation_test_per_device<half>(device));
    CALL_SUBTEST(sycl_inflation_test_per_device<float>(device));
  }
}
