// 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 <iostream>
#include <chrono>
#include <ctime>

#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_simple_striding(const Eigen::SyclDevice& sycl_device) {
  Eigen::array<IndexType, 4> tensor_dims = {{2, 3, 5, 7}};
  Eigen::array<IndexType, 4> stride_dims = {{1, 1, 3, 3}};

  Tensor<DataType, 4, DataLayout, IndexType> tensor(tensor_dims);
  Tensor<DataType, 4, DataLayout, IndexType> no_stride(tensor_dims);
  Tensor<DataType, 4, DataLayout, IndexType> stride(stride_dims);

  std::size_t tensor_bytes = tensor.size() * sizeof(DataType);
  std::size_t no_stride_bytes = no_stride.size() * sizeof(DataType);
  std::size_t stride_bytes = stride.size() * sizeof(DataType);
  DataType* d_tensor = static_cast<DataType*>(sycl_device.allocate(tensor_bytes));
  DataType* d_no_stride = static_cast<DataType*>(sycl_device.allocate(no_stride_bytes));
  DataType* d_stride = static_cast<DataType*>(sycl_device.allocate(stride_bytes));

  Eigen::TensorMap<Eigen::Tensor<DataType, 4, DataLayout, IndexType> > gpu_tensor(d_tensor, tensor_dims);
  Eigen::TensorMap<Eigen::Tensor<DataType, 4, DataLayout, IndexType> > gpu_no_stride(d_no_stride, tensor_dims);
  Eigen::TensorMap<Eigen::Tensor<DataType, 4, DataLayout, IndexType> > gpu_stride(d_stride, stride_dims);

  tensor.setRandom();
  array<IndexType, 4> strides;
  strides[0] = 1;
  strides[1] = 1;
  strides[2] = 1;
  strides[3] = 1;
  sycl_device.memcpyHostToDevice(d_tensor, tensor.data(), tensor_bytes);
  gpu_no_stride.device(sycl_device) = gpu_tensor.stride(strides);
  sycl_device.memcpyDeviceToHost(no_stride.data(), d_no_stride, no_stride_bytes);

  // no_stride = tensor.stride(strides);

  VERIFY_IS_EQUAL(no_stride.dimension(0), 2);
  VERIFY_IS_EQUAL(no_stride.dimension(1), 3);
  VERIFY_IS_EQUAL(no_stride.dimension(2), 5);
  VERIFY_IS_EQUAL(no_stride.dimension(3), 7);

  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;
  // Tensor<float, 4, DataLayout> stride;
  //   stride = tensor.stride(strides);

  gpu_stride.device(sycl_device) = gpu_tensor.stride(strides);
  sycl_device.memcpyDeviceToHost(stride.data(), d_stride, stride_bytes);

  VERIFY_IS_EQUAL(stride.dimension(0), 1);
  VERIFY_IS_EQUAL(stride.dimension(1), 1);
  VERIFY_IS_EQUAL(stride.dimension(2), 3);
  VERIFY_IS_EQUAL(stride.dimension(3), 3);

  for (IndexType i = 0; i < 1; ++i) {
    for (IndexType j = 0; j < 1; ++j) {
      for (IndexType k = 0; k < 3; ++k) {
        for (IndexType l = 0; l < 3; ++l) {
          VERIFY_IS_EQUAL(tensor(2 * i, 4 * j, 2 * k, 3 * l), stride(i, j, k, l));
        }
      }
    }
  }

  sycl_device.deallocate(d_tensor);
  sycl_device.deallocate(d_no_stride);
  sycl_device.deallocate(d_stride);
}

template <typename DataType, int DataLayout, typename IndexType>
static void test_striding_as_lvalue(const Eigen::SyclDevice& sycl_device) {
  Eigen::array<IndexType, 4> tensor_dims = {{2, 3, 5, 7}};
  Eigen::array<IndexType, 4> stride_dims = {{3, 12, 10, 21}};

  Tensor<DataType, 4, DataLayout, IndexType> tensor(tensor_dims);
  Tensor<DataType, 4, DataLayout, IndexType> no_stride(stride_dims);
  Tensor<DataType, 4, DataLayout, IndexType> stride(stride_dims);

  std::size_t tensor_bytes = tensor.size() * sizeof(DataType);
  std::size_t no_stride_bytes = no_stride.size() * sizeof(DataType);
  std::size_t stride_bytes = stride.size() * sizeof(DataType);

  DataType* d_tensor = static_cast<DataType*>(sycl_device.allocate(tensor_bytes));
  DataType* d_no_stride = static_cast<DataType*>(sycl_device.allocate(no_stride_bytes));
  DataType* d_stride = static_cast<DataType*>(sycl_device.allocate(stride_bytes));

  Eigen::TensorMap<Eigen::Tensor<DataType, 4, DataLayout, IndexType> > gpu_tensor(d_tensor, tensor_dims);
  Eigen::TensorMap<Eigen::Tensor<DataType, 4, DataLayout, IndexType> > gpu_no_stride(d_no_stride, stride_dims);
  Eigen::TensorMap<Eigen::Tensor<DataType, 4, DataLayout, IndexType> > gpu_stride(d_stride, stride_dims);

  // Tensor<float, 4, DataLayout> tensor(2,3,5,7);
  tensor.setRandom();
  array<IndexType, 4> strides;
  strides[0] = 2;
  strides[1] = 4;
  strides[2] = 2;
  strides[3] = 3;

  //  Tensor<float, 4, DataLayout> result(3, 12, 10, 21);
  //  result.stride(strides) = tensor;
  sycl_device.memcpyHostToDevice(d_tensor, tensor.data(), tensor_bytes);
  gpu_stride.stride(strides).device(sycl_device) = gpu_tensor;
  sycl_device.memcpyDeviceToHost(stride.data(), d_stride, stride_bytes);

  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), stride(2 * i, 4 * j, 2 * k, 3 * l));
        }
      }
    }
  }

  array<IndexType, 4> no_strides;
  no_strides[0] = 1;
  no_strides[1] = 1;
  no_strides[2] = 1;
  no_strides[3] = 1;
  //  Tensor<float, 4, DataLayout> result2(3, 12, 10, 21);
  //  result2.stride(strides) = tensor.stride(no_strides);

  gpu_no_stride.stride(strides).device(sycl_device) = gpu_tensor.stride(no_strides);
  sycl_device.memcpyDeviceToHost(no_stride.data(), d_no_stride, no_stride_bytes);

  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(2 * i, 4 * j, 2 * k, 3 * l));
        }
      }
    }
  }
  sycl_device.deallocate(d_tensor);
  sycl_device.deallocate(d_no_stride);
  sycl_device.deallocate(d_stride);
}

template <typename Dev_selector>
void tensorStridingPerDevice(Dev_selector& s) {
  QueueInterface queueInterface(s);
  auto sycl_device = Eigen::SyclDevice(&queueInterface);
  test_simple_striding<float, ColMajor, int64_t>(sycl_device);
  test_simple_striding<float, RowMajor, int64_t>(sycl_device);
  test_striding_as_lvalue<float, ColMajor, int64_t>(sycl_device);
  test_striding_as_lvalue<float, RowMajor, int64_t>(sycl_device);
}

EIGEN_DECLARE_TEST(tensor_striding_sycl) {
  for (const auto& device : Eigen::get_sycl_supported_devices()) {
    CALL_SUBTEST(tensorStridingPerDevice(device));
  }
}
