// 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;
using Eigen::TensorMap;

static void test_additions() {
  Tensor<std::complex<float>, 1> data1(3);
  Tensor<std::complex<float>, 1> data2(3);
  for (int i = 0; i < 3; ++i) {
    data1(i) = std::complex<float>(i, -i);
    data2(i) = std::complex<float>(i, 7 * i);
  }

  Tensor<std::complex<float>, 1> sum = data1 + data2;
  for (int i = 0; i < 3; ++i) {
    VERIFY_IS_EQUAL(sum(i), std::complex<float>(2 * i, 6 * i));
  }
}

static void test_abs() {
  Tensor<std::complex<float>, 1> data1(3);
  Tensor<std::complex<double>, 1> data2(3);
  data1.setRandom();
  data2.setRandom();

  Tensor<float, 1> abs1 = data1.abs();
  Tensor<double, 1> abs2 = data2.abs();
  for (int i = 0; i < 3; ++i) {
    VERIFY_IS_APPROX(abs1(i), std::abs(data1(i)));
    VERIFY_IS_APPROX(abs2(i), std::abs(data2(i)));
  }
}

static void test_arg() {
  Tensor<std::complex<float>, 1> data1(3);
  Tensor<std::complex<double>, 1> data2(3);
  data1.setRandom();
  data2.setRandom();

  Tensor<float, 1> arg1 = data1.arg();
  Tensor<double, 1> arg2 = data2.arg();
  for (int i = 0; i < 3; ++i) {
    VERIFY_IS_APPROX(arg1(i), std::arg(data1(i)));
    VERIFY_IS_APPROX(arg2(i), std::arg(data2(i)));
  }
}

static void test_conjugate() {
  Tensor<std::complex<float>, 1> data1(3);
  Tensor<std::complex<double>, 1> data2(3);
  Tensor<int, 1> data3(3);
  data1.setRandom();
  data2.setRandom();
  data3.setRandom();

  Tensor<std::complex<float>, 1> conj1 = data1.conjugate();
  Tensor<std::complex<double>, 1> conj2 = data2.conjugate();
  Tensor<int, 1> conj3 = data3.conjugate();
  for (int i = 0; i < 3; ++i) {
    VERIFY_IS_APPROX(conj1(i), std::conj(data1(i)));
    VERIFY_IS_APPROX(conj2(i), std::conj(data2(i)));
    VERIFY_IS_APPROX(conj3(i), data3(i));
  }
}

static void test_contractions() {
  Tensor<std::complex<float>, 4> t_left(30, 50, 8, 31);
  Tensor<std::complex<float>, 5> t_right(8, 31, 7, 20, 10);
  Tensor<std::complex<float>, 5> t_result(30, 50, 7, 20, 10);

  t_left.setRandom();
  t_right.setRandom();

  typedef Map<Matrix<std::complex<float>, Dynamic, Dynamic>> MapXcf;
  MapXcf m_left(t_left.data(), 1500, 248);
  MapXcf m_right(t_right.data(), 248, 1400);
  Matrix<std::complex<float>, Dynamic, Dynamic> m_result(1500, 1400);

  // This contraction should be equivalent to a regular matrix multiplication
  typedef Tensor<float, 1>::DimensionPair DimPair;
  Eigen::array<DimPair, 2> dims;
  dims[0] = DimPair(2, 0);
  dims[1] = DimPair(3, 1);
  t_result = t_left.contract(t_right, dims);
  m_result = m_left * m_right;
  for (int i = 0; i < t_result.dimensions().TotalSize(); i++) {
    VERIFY_IS_APPROX(t_result.data()[i], m_result.data()[i]);
  }
}

EIGEN_DECLARE_TEST(cxx11_tensor_of_complex) {
  CALL_SUBTEST(test_additions());
  CALL_SUBTEST(test_abs());
  CALL_SUBTEST(test_arg());
  CALL_SUBTEST(test_conjugate());
  CALL_SUBTEST(test_contractions());
}
