// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
// Copyright (C) 2014-2015 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/.

#ifndef EIGEN_CXX11_TENSOR_TENSORSTORAGE_H
#define EIGEN_CXX11_TENSOR_TENSORSTORAGE_H

#ifdef EIGEN_TENSOR_STORAGE_CTOR_PLUGIN
#define EIGEN_INTERNAL_TENSOR_STORAGE_CTOR_PLUGIN EIGEN_TENSOR_STORAGE_CTOR_PLUGIN;
#else
#define EIGEN_INTERNAL_TENSOR_STORAGE_CTOR_PLUGIN
#endif

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

/** \internal
 *
 * \class TensorStorage
 * \ingroup CXX11_Tensor_Module
 *
 * \brief Stores the data of a tensor
 *
 * This class stores the data of fixed-size, dynamic-size or mixed tensors
 * in a way as compact as possible.
 *
 * \sa Tensor
 */
template <typename T, typename Dimensions, int Options>
class TensorStorage;

// Pure fixed-size storage
template <typename T, typename FixedDimensions, int Options_>
class TensorStorage {
 private:
  static constexpr std::size_t Size = FixedDimensions::total_size;

  // Allocate an array of size at least one to prevent compiler warnings.
  static constexpr std::size_t MinSize = max_n_1<Size>::size;
  EIGEN_ALIGN_MAX T m_data[MinSize];

 public:
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE TensorStorage() {}

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T* data() { return m_data; }
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T* data() const { return m_data; }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const FixedDimensions dimensions() const { return FixedDimensions(); }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseIndex size() const { return Size; }
};

// pure dynamic
template <typename T, typename IndexType, int NumIndices_, int Options_>
class TensorStorage<T, DSizes<IndexType, NumIndices_>, Options_> {
 public:
  typedef IndexType Index;
  typedef DSizes<IndexType, NumIndices_> Dimensions;
  typedef TensorStorage<T, DSizes<IndexType, NumIndices_>, Options_> Self;

  EIGEN_DEVICE_FUNC TensorStorage() : m_data(0), m_dimensions() {
    if (NumIndices_ == 0) {
      m_data = internal::conditional_aligned_new_auto<T, (Options_ & DontAlign) == 0>(1);
    }
  }
  EIGEN_DEVICE_FUNC TensorStorage(internal::constructor_without_unaligned_array_assert)
      : m_data(0), m_dimensions(internal::template repeat<NumIndices_, Index>(0)) {}
  EIGEN_DEVICE_FUNC TensorStorage(Index size, const array<Index, NumIndices_>& dimensions)
      : m_data(internal::conditional_aligned_new_auto<T, (Options_ & DontAlign) == 0>(size)), m_dimensions(dimensions) {
    EIGEN_INTERNAL_TENSOR_STORAGE_CTOR_PLUGIN
  }

  template <typename... DenseIndex>
  EIGEN_DEVICE_FUNC TensorStorage(DenseIndex... indices) : m_dimensions(indices...) {
    m_data = internal::conditional_aligned_new_auto<T, (Options_ & DontAlign) == 0>(internal::array_prod(m_dimensions));
  }

  EIGEN_DEVICE_FUNC TensorStorage(const Self& other)
      : m_data(internal::conditional_aligned_new_auto<T, (Options_ & DontAlign) == 0>(
            internal::array_prod(other.m_dimensions))),
        m_dimensions(other.m_dimensions) {
    internal::smart_copy(other.m_data, other.m_data + internal::array_prod(other.m_dimensions), m_data);
  }
  EIGEN_DEVICE_FUNC Self& operator=(const Self& other) {
    if (this != &other) {
      Self tmp(other);
      this->swap(tmp);
    }
    return *this;
  }

  EIGEN_DEVICE_FUNC TensorStorage(Self&& other) : TensorStorage() { *this = std::move(other); }

  EIGEN_DEVICE_FUNC Self& operator=(Self&& other) {
    numext::swap(m_data, other.m_data);
    numext::swap(m_dimensions, other.m_dimensions);
    return *this;
  }

  EIGEN_DEVICE_FUNC ~TensorStorage() {
    internal::conditional_aligned_delete_auto<T, (Options_ & DontAlign) == 0>(m_data,
                                                                              internal::array_prod(m_dimensions));
  }
  EIGEN_DEVICE_FUNC void swap(Self& other) {
    numext::swap(m_data, other.m_data);
    numext::swap(m_dimensions, other.m_dimensions);
  }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Dimensions& dimensions() const { return m_dimensions; }

  EIGEN_DEVICE_FUNC void resize(Index size, const array<Index, NumIndices_>& nbDimensions) {
    const Index currentSz = internal::array_prod(m_dimensions);
    if (size != currentSz) {
      internal::conditional_aligned_delete_auto<T, (Options_ & DontAlign) == 0>(m_data, currentSz);
      if (size)
        m_data = internal::conditional_aligned_new_auto<T, (Options_ & DontAlign) == 0>(size);
      else if (NumIndices_ == 0) {
        m_data = internal::conditional_aligned_new_auto<T, (Options_ & DontAlign) == 0>(1);
      } else
        m_data = 0;
      EIGEN_INTERNAL_DENSE_STORAGE_CTOR_PLUGIN({})
    }
    m_dimensions = nbDimensions;
  }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE T* data() { return m_data; }
  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const T* data() const { return m_data; }

  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Index size() const { return m_dimensions.TotalSize(); }

 private:
  T* m_data;
  Dimensions m_dimensions;
};

}  // end namespace Eigen

#endif  // EIGEN_CXX11_TENSOR_TENSORSTORAGE_H
