// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 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/.

#include "main.h"

#include <Eigen/CXX11/Tensor>

using Eigen::Tensor;

template <int DataLayout>
static void test_dimension_failures() {
  Tensor<int, 3, DataLayout> left(2, 3, 1);
  Tensor<int, 3, DataLayout> right(3, 3, 1);
  left.setRandom();
  right.setRandom();

  // Okay; other dimensions are equal.
  Tensor<int, 3, DataLayout> concatenation = left.concatenate(right, 0);

  // Dimension mismatches.
  VERIFY_RAISES_ASSERT(concatenation = left.concatenate(right, 1));
  VERIFY_RAISES_ASSERT(concatenation = left.concatenate(right, 2));

  // Axis > NumDims or < 0.
  VERIFY_RAISES_ASSERT(concatenation = left.concatenate(right, 3));
  VERIFY_RAISES_ASSERT(concatenation = left.concatenate(right, -1));
}

template <int DataLayout>
static void test_static_dimension_failure() {
  Tensor<int, 2, DataLayout> left(2, 3);
  Tensor<int, 3, DataLayout> right(2, 3, 1);

#ifdef CXX11_TENSOR_CONCATENATION_STATIC_DIMENSION_FAILURE
  // Technically compatible, but we static assert that the inputs have same
  // NumDims.
  Tensor<int, 3, DataLayout> concatenation = left.concatenate(right, 0);
#endif

  // This can be worked around in this case.
  Tensor<int, 3, DataLayout> concatenation = left.reshape(Tensor<int, 3>::Dimensions(2, 3, 1)).concatenate(right, 0);
  Tensor<int, 2, DataLayout> alternative = left
                                               // Clang compiler break with {{{}}} with an ambiguous error on copy
                                               // constructor the variadic DSize constructor added for #ifndef
                                               // EIGEN_EMULATE_CXX11_META_H. Solution: either the code should change to
                                               //  Tensor<int, 2>::Dimensions{{2, 3}}
                                               // or Tensor<int, 2>::Dimensions{Tensor<int, 2>::Dimensions{{2, 3}}}
                                               .concatenate(right.reshape(Tensor<int, 2>::Dimensions(2, 3)), 0);
}

template <int DataLayout>
static void test_simple_concatenation() {
  Tensor<int, 3, DataLayout> left(2, 3, 1);
  Tensor<int, 3, DataLayout> right(2, 3, 1);
  left.setRandom();
  right.setRandom();

  Tensor<int, 3, DataLayout> concatenation = left.concatenate(right, 0);
  VERIFY_IS_EQUAL(concatenation.dimension(0), 4);
  VERIFY_IS_EQUAL(concatenation.dimension(1), 3);
  VERIFY_IS_EQUAL(concatenation.dimension(2), 1);
  for (int j = 0; j < 3; ++j) {
    for (int i = 0; i < 2; ++i) {
      VERIFY_IS_EQUAL(concatenation(i, j, 0), left(i, j, 0));
    }
    for (int i = 2; i < 4; ++i) {
      VERIFY_IS_EQUAL(concatenation(i, j, 0), right(i - 2, j, 0));
    }
  }

  concatenation = left.concatenate(right, 1);
  VERIFY_IS_EQUAL(concatenation.dimension(0), 2);
  VERIFY_IS_EQUAL(concatenation.dimension(1), 6);
  VERIFY_IS_EQUAL(concatenation.dimension(2), 1);
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      VERIFY_IS_EQUAL(concatenation(i, j, 0), left(i, j, 0));
    }
    for (int j = 3; j < 6; ++j) {
      VERIFY_IS_EQUAL(concatenation(i, j, 0), right(i, j - 3, 0));
    }
  }

  concatenation = left.concatenate(right, 2);
  VERIFY_IS_EQUAL(concatenation.dimension(0), 2);
  VERIFY_IS_EQUAL(concatenation.dimension(1), 3);
  VERIFY_IS_EQUAL(concatenation.dimension(2), 2);
  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      VERIFY_IS_EQUAL(concatenation(i, j, 0), left(i, j, 0));
      VERIFY_IS_EQUAL(concatenation(i, j, 1), right(i, j, 0));
    }
  }
}

// TODO(phli): Add test once we have a real vectorized implementation.
// static void test_vectorized_concatenation() {}

static void test_concatenation_as_lvalue() {
  Tensor<int, 2> t1(2, 3);
  Tensor<int, 2> t2(2, 3);
  t1.setRandom();
  t2.setRandom();

  Tensor<int, 2> result(4, 3);
  result.setRandom();
  t1.concatenate(t2, 0) = result;

  for (int i = 0; i < 2; ++i) {
    for (int j = 0; j < 3; ++j) {
      VERIFY_IS_EQUAL(t1(i, j), result(i, j));
      VERIFY_IS_EQUAL(t2(i, j), result(i + 2, j));
    }
  }
}

EIGEN_DECLARE_TEST(cxx11_tensor_concatenation) {
  CALL_SUBTEST(test_dimension_failures<ColMajor>());
  CALL_SUBTEST(test_dimension_failures<RowMajor>());
  CALL_SUBTEST(test_static_dimension_failure<ColMajor>());
  CALL_SUBTEST(test_static_dimension_failure<RowMajor>());
  CALL_SUBTEST(test_simple_concatenation<ColMajor>());
  CALL_SUBTEST(test_simple_concatenation<RowMajor>());
  // CALL_SUBTEST(test_vectorized_concatenation());
  CALL_SUBTEST(test_concatenation_as_lvalue());
}
