// 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>
// Benoit Steiner <benoit.steiner.goog@gmail.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_simple_shuffling_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_shuffle(tensorRange);
  tensor.setRandom();

  const size_t buffSize = tensor.size() * sizeof(DataType);
  array<IndexType, 4> shuffles;
  shuffles[0] = 0;
  shuffles[1] = 1;
  shuffles[2] = 2;
  shuffles[3] = 3;
  DataType* gpu_data1 = static_cast<DataType*>(sycl_device.allocate(buffSize));
  DataType* gpu_data2 = static_cast<DataType*>(sycl_device.allocate(buffSize));

  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu1(gpu_data1, tensorRange);
  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu2(gpu_data2, tensorRange);

  sycl_device.memcpyHostToDevice(gpu_data1, tensor.data(), buffSize);

  gpu2.device(sycl_device) = gpu1.shuffle(shuffles);
  sycl_device.memcpyDeviceToHost(no_shuffle.data(), gpu_data2, buffSize);
  sycl_device.synchronize();

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

  for (IndexType i = 0; i < sizeDim1; ++i) {
    for (IndexType j = 0; j < sizeDim2; ++j) {
      for (IndexType k = 0; k < sizeDim3; ++k) {
        for (IndexType l = 0; l < sizeDim4; ++l) {
          VERIFY_IS_EQUAL(tensor(i, j, k, l), no_shuffle(i, j, k, l));
        }
      }
    }
  }

  shuffles[0] = 2;
  shuffles[1] = 3;
  shuffles[2] = 1;
  shuffles[3] = 0;
  array<IndexType, 4> tensorrangeShuffle = {{sizeDim3, sizeDim4, sizeDim2, sizeDim1}};
  Tensor<DataType, 4, DataLayout, IndexType> shuffle(tensorrangeShuffle);
  DataType* gpu_data3 = static_cast<DataType*>(sycl_device.allocate(buffSize));
  TensorMap<Tensor<DataType, 4, DataLayout, IndexType>> gpu3(gpu_data3, tensorrangeShuffle);

  gpu3.device(sycl_device) = gpu1.shuffle(shuffles);
  sycl_device.memcpyDeviceToHost(shuffle.data(), gpu_data3, buffSize);
  sycl_device.synchronize();

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

  for (IndexType i = 0; i < sizeDim1; ++i) {
    for (IndexType j = 0; j < sizeDim2; ++j) {
      for (IndexType k = 0; k < sizeDim3; ++k) {
        for (IndexType l = 0; l < sizeDim4; ++l) {
          VERIFY_IS_EQUAL(tensor(i, j, k, l), shuffle(k, l, j, i));
        }
      }
    }
  }
}

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