// 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/.
// SPDX-License-Identifier: MPL-2.0

#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 10
// GCC loses nested initializer-list bounds after inlining small heap-allocated tensors.
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif

#include "main.h"

#include <sstream>
#include <Eigen/Tensor>

template <typename Scalar, int rank, int Layout>
struct test_tensor_ostream_impl {};

template <typename Scalar, int Layout>
struct test_tensor_ostream_impl<Scalar, 0, Layout> {
  static void run() {
    Eigen::Tensor<Scalar, 0, Layout> t;
    t.setValues(1);
    std::ostringstream os;
    os << t.format(Eigen::TensorIOFormat::Plain());
    VERIFY(os.str() == "1");
  }
};

template <typename Scalar, int Layout>
struct test_tensor_ostream_impl<Scalar, 1, Layout> {
  static void run() {
    Eigen::Tensor<Scalar, 1, Layout> t = {3};
    t.setValues({1, 2, 3});
    std::ostringstream os;
    os << t.format(Eigen::TensorIOFormat::Plain());
    VERIFY(os.str() == "1 2 3");
  }
};

template <typename Scalar, int Layout>
struct test_tensor_ostream_impl<Scalar, 2, Layout> {
  static void run() {
    Eigen::Tensor<Scalar, 2, Layout> t = {3, 2};
    t.setValues({{1, 2}, {3, 4}, {5, 6}});
    std::ostringstream os;
    os << t.format(Eigen::TensorIOFormat::Plain());
    VERIFY(os.str() == "1 2\n3 4\n5 6");
  }
};

template <typename Scalar, int Layout>
struct test_tensor_ostream_impl<Scalar, 3, Layout> {
  static void run() {
    Eigen::Tensor<Scalar, 3, Layout> t = {4, 3, 2};
    t.setValues({{{1, 2}, {3, 4}, {5, 6}},
                 {{7, 8}, {9, 10}, {11, 12}},
                 {{13, 14}, {15, 16}, {17, 18}},
                 {{19, 20}, {21, 22}, {23, 24}}});
    std::ostringstream os;
    os << t.format(Eigen::TensorIOFormat::Plain());
    VERIFY(os.str() == " 1  2\n 3  4\n 5  6\n\n 7  8\n 9 10\n11 12\n\n13 14\n15 16\n17 18\n\n19 20\n21 22\n23 24");
  }
};

template <int Layout>
struct test_tensor_ostream_impl<bool, 2, Layout> {
  static void run() {
    Eigen::Tensor<bool, 2, Layout> t = {3, 2};
    t.setValues({{false, true}, {true, false}, {false, false}});
    std::ostringstream os;
    os << t.format(Eigen::TensorIOFormat::Plain());
    VERIFY(os.str() == "0 1\n1 0\n0 0");
  }
};

template <typename Scalar, int Layout>
struct test_tensor_ostream_impl<std::complex<Scalar>, 2, Layout> {
  static void run() {
    Eigen::Tensor<std::complex<Scalar>, 2, Layout> t = {3, 2};
    t.setValues({{std::complex<Scalar>(1, 2), std::complex<Scalar>(12, 3)},
                 {std::complex<Scalar>(-4, 2), std::complex<Scalar>(0, 5)},
                 {std::complex<Scalar>(-1, 4), std::complex<Scalar>(5, 27)}});
    std::ostringstream os;
    os << t.format(Eigen::TensorIOFormat::Plain());
    VERIFY(os.str() == " (1,2) (12,3)\n(-4,2)  (0,5)\n(-1,4) (5,27)");

    os.str("");
    os.clear();
    os << t.format(Eigen::TensorIOFormat::Numpy());
    VERIFY(os.str() == "[[ 1+2j 12+3j]\n [-4+2j  0+5j]\n [-1+4j 5+27j]]");

    os.str("");
    os.clear();
    os << t.format(Eigen::TensorIOFormat::Native());
    VERIFY(os.str() == "{{ {1, 2}, {12, 3}},\n {{-4, 2},  {0, 5}},\n {{-1, 4}, {5, 27}}}");
  }
};

template <typename Scalar, int rank, int Layout>
void test_tensor_ostream() {
  test_tensor_ostream_impl<Scalar, rank, Layout>::run();
}

void test_const_tensor_ostream() {
  Eigen::Tensor<float, 0> t;
  t.setValues(1);
  const Eigen::TensorMap<Eigen::Tensor<const float, 0, Eigen::RowMajor>, Eigen::Unaligned> t_const(
      t.data(), Eigen::DSizes<Eigen::DenseIndex, 0>{});
  std::ostringstream os;
  os << t_const.format(Eigen::TensorIOFormat::Plain());
  VERIFY(os.str() == "1");
}

EIGEN_DECLARE_TEST(tensor_io) {
  CALL_SUBTEST((test_tensor_ostream<float, 0, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<float, 1, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<float, 2, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<float, 3, Eigen::ColMajor>()));

  CALL_SUBTEST((test_tensor_ostream<double, 0, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<double, 1, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<double, 2, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<double, 3, Eigen::ColMajor>()));

  CALL_SUBTEST((test_tensor_ostream<int, 0, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<int, 1, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<int, 2, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<int, 3, Eigen::ColMajor>()));

  CALL_SUBTEST((test_tensor_ostream<float, 0, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<float, 1, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<float, 2, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<float, 3, Eigen::RowMajor>()));

  CALL_SUBTEST((test_tensor_ostream<double, 0, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<double, 1, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<double, 2, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<double, 3, Eigen::RowMajor>()));

  CALL_SUBTEST((test_tensor_ostream<int, 0, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<int, 1, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<int, 2, Eigen::RowMajor>()));
  CALL_SUBTEST((test_tensor_ostream<int, 3, Eigen::RowMajor>()));

  // 8-bit integers print as numbers, not as characters.
  CALL_SUBTEST((test_tensor_ostream<Eigen::numext::int8_t, 2, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<Eigen::numext::uint8_t, 3, Eigen::RowMajor>()));

  CALL_SUBTEST((test_tensor_ostream<bool, 2, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<bool, 2, Eigen::RowMajor>()));

  CALL_SUBTEST((test_tensor_ostream<std::complex<double>, 2, Eigen::ColMajor>()));
  CALL_SUBTEST((test_tensor_ostream<std::complex<float>, 2, Eigen::ColMajor>()));

  // Test printing TensorMap with const elements.
  CALL_SUBTEST((test_const_tensor_ostream()));
}
