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

#include "./InternalHeaderCheck.h"

namespace Eigen {

enum {
  NegationFlag           = 0x01,
  ConjugationFlag        = 0x02
};

enum {
  GlobalRealFlag         = 0x01,
  GlobalImagFlag         = 0x02,
  GlobalZeroFlag         = 0x03
};

namespace internal {

template<std::size_t NumIndices, typename... Sym>                   struct tensor_symmetry_pre_analysis;
template<std::size_t NumIndices, typename... Sym>                   struct tensor_static_symgroup;
template<bool instantiate, std::size_t NumIndices, typename... Sym> struct tensor_static_symgroup_if;
template<typename Tensor_> struct tensor_symmetry_calculate_flags;
template<typename Tensor_> struct tensor_symmetry_assign_value;
template<typename... Sym> struct tensor_symmetry_num_indices;

} // end namespace internal

template<int One_, int Two_>
struct Symmetry
{
  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
  constexpr static int One = One_;
  constexpr static int Two = Two_;
  constexpr static int Flags = 0;
};

template<int One_, int Two_>
struct AntiSymmetry
{
  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
  constexpr static int One = One_;
  constexpr static int Two = Two_;
  constexpr static int Flags = NegationFlag;
};

template<int One_, int Two_>
struct Hermiticity
{
  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
  constexpr static int One = One_;
  constexpr static int Two = Two_;
  constexpr static int Flags = ConjugationFlag;
};

template<int One_, int Two_>
struct AntiHermiticity
{
  static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
  constexpr static int One = One_;
  constexpr static int Two = Two_;
  constexpr static int Flags = ConjugationFlag | NegationFlag;
};

/** \class DynamicSGroup
  * \ingroup TensorSymmetry_Module
  *
  * \brief Dynamic symmetry group
  *
  * The %DynamicSGroup class represents a symmetry group that need not be known at
  * compile time. It is useful if one wants to support arbitrary run-time defineable
  * symmetries for tensors, but it is also instantiated if a symmetry group is defined
  * at compile time that would be either too large for the compiler to reasonably
  * generate (using templates to calculate this at compile time is very inefficient)
  * or that the compiler could generate the group but that it wouldn't make sense to
  * unroll the loop for setting coefficients anymore.
  */
class DynamicSGroup;

/** \internal
  *
  * \class DynamicSGroupFromTemplateArgs
  * \ingroup TensorSymmetry_Module
  *
  * \brief Dynamic symmetry group, initialized from template arguments
  *
  * This class is a child class of DynamicSGroup. It uses the template arguments
  * specified to initialize itself.
  */
template<typename... Gen>
class DynamicSGroupFromTemplateArgs;

/** \class StaticSGroup
  * \ingroup TensorSymmetry_Module
  *
  * \brief Static symmetry group
  *
  * This class represents a symmetry group that is known and resolved completely
  * at compile time. Ideally, no run-time penalty is incurred compared to the
  * manual unrolling of the symmetry.
  *
  * <b><i>CAUTION:</i></b>
  *
  * Do not use this class directly for large symmetry groups. The compiler
  * may run into a limit, or segfault or in the very least will take a very,
  * very, very long time to compile the code. Use the SGroup class instead
  * if you want a static group. That class contains logic that will
  * automatically select the DynamicSGroup class instead if the symmetry
  * group becomes too large. (In that case, unrolling may not even be
  * beneficial.)
  */
template<typename... Gen>
class StaticSGroup;

/** \class SGroup
  * \ingroup TensorSymmetry_Module
  *
  * \brief Symmetry group, initialized from template arguments
  *
  * This class represents a symmetry group whose generators are already
  * known at compile time. It may or may not be resolved at compile time,
  * depending on the estimated size of the group.
  *
  * \sa StaticSGroup
  * \sa DynamicSGroup
  */
template<typename... Gen>
class SGroup : public internal::tensor_symmetry_pre_analysis<internal::tensor_symmetry_num_indices<Gen...>::value, Gen...>::root_type
{
  public:
    constexpr static std::size_t NumIndices = internal::tensor_symmetry_num_indices<Gen...>::value;
    typedef typename internal::tensor_symmetry_pre_analysis<NumIndices, Gen...>::root_type Base;

    // make standard constructors + assignment operators public
    inline SGroup() : Base() { }
    inline SGroup(const SGroup<Gen...>& other) : Base(other) { }
    inline SGroup(SGroup<Gen...>&& other) : Base(other) { }
    inline SGroup<Gen...>& operator=(const SGroup<Gen...>& other) { Base::operator=(other); return *this; }
    inline SGroup<Gen...>& operator=(SGroup<Gen...>&& other) { Base::operator=(other); return *this; }

    // all else is defined in the base class
};

namespace internal {

template<typename... Sym> struct tensor_symmetry_num_indices
{
  constexpr static std::size_t value = 1;
};

template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...>
{
private:
  constexpr static std::size_t One = static_cast<std::size_t>(One_);
  constexpr static std::size_t Two = static_cast<std::size_t>(Two_);
  constexpr static std::size_t Three = tensor_symmetry_num_indices<Sym...>::value;

  // don't use std::max, since it's not constexpr until C++14...
  constexpr static std::size_t maxOneTwoPlusOne = ((One > Two) ? One : Two) + 1;
public:
  constexpr static std::size_t value = (maxOneTwoPlusOne > Three) ? maxOneTwoPlusOne : Three;
};

template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<AntiSymmetry<One_, Two_>, Sym...>
  : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<Hermiticity<One_, Two_>, Sym...>
  : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};
template<int One_, int Two_, typename... Sym> struct tensor_symmetry_num_indices<AntiHermiticity<One_, Two_>, Sym...>
  : public tensor_symmetry_num_indices<Symmetry<One_, Two_>, Sym...> {};

/** \internal
  *
  * \class tensor_symmetry_pre_analysis
  * \ingroup TensorSymmetry_Module
  *
  * \brief Pre-select whether to use a static or dynamic symmetry group
  *
  * When a symmetry group could in principle be determined at compile time,
  * this template implements the logic whether to actually do that or whether
  * to rather defer that to runtime.
  *
  * The logic is as follows:
  * <dl>
  * <dt><b>No generators (trivial symmetry):</b></dt>
  * <dd>Use a trivial static group. Ideally, this has no performance impact
  *     compared to not using symmetry at all. In practice, this might not
  *     be the case.</dd>
  * <dt><b>More than 4 generators:</b></dt>
  * <dd>Calculate the group at run time, it is likely far too large for the
  *     compiler to be able to properly generate it in a realistic time.</dd>
  * <dt><b>Up to and including 4 generators:</b></dt>
  * <dd>Actually enumerate all group elements, but then check how many there
  *     are. If there are more than 16, it is unlikely that unrolling the
  *     loop (as is done in the static compile-time case) is sensible, so
  *     use a dynamic group instead. If there are at most 16 elements, actually
  *     use that static group. Note that the largest group with 4 generators
  *     still compiles with reasonable resources.</dd>
  * </dl>
  *
  * Note: Example compile time performance with g++-4.6 on an Intenl Core i5-3470
  *       with 16 GiB RAM (all generators non-redundant and the subgroups don't
  *       factorize):
  *
  *          # Generators          -O0 -ggdb               -O2
  *          -------------------------------------------------------------------
  *          1                 0.5 s  /   250 MiB     0.45s /   230 MiB
  *          2                 0.5 s  /   260 MiB     0.5 s /   250 MiB
  *          3                 0.65s  /   310 MiB     0.62s /   310 MiB
  *          4                 2.2 s  /   860 MiB     1.7 s /   770 MiB
  *          5               130   s  / 13000 MiB   120   s / 11000 MiB
  *
  * It is clear that everything is still very efficient up to 4 generators, then
  * the memory and CPU requirements become unreasonable. Thus we only instantiate
  * the template group theory logic if the number of generators supplied is 4 or
  * lower, otherwise this will be forced to be done during runtime, where the
  * algorithm is reasonably fast.
  */
template<std::size_t NumIndices>
struct tensor_symmetry_pre_analysis<NumIndices>
{
  typedef StaticSGroup<> root_type;
};

template<std::size_t NumIndices, typename Gen_, typename... Gens_>
struct tensor_symmetry_pre_analysis<NumIndices, Gen_, Gens_...>
{
  constexpr static std::size_t max_static_generators = 4;
  constexpr static std::size_t max_static_elements = 16;
  typedef tensor_static_symgroup_if<(sizeof...(Gens_) + 1 <= max_static_generators), NumIndices, Gen_, Gens_...> helper;
  constexpr static std::size_t possible_size = helper::size;

  typedef std::conditional_t<
    possible_size == 0 || possible_size >= max_static_elements,
    DynamicSGroupFromTemplateArgs<Gen_, Gens_...>,
    typename helper::type
  > root_type;
};

template<bool instantiate, std::size_t NumIndices, typename... Gens>
struct tensor_static_symgroup_if
{
  constexpr static std::size_t size = 0;
  typedef void type;
};

template<std::size_t NumIndices, typename... Gens>
struct tensor_static_symgroup_if<true, NumIndices, Gens...> : tensor_static_symgroup<NumIndices, Gens...> {};

template<typename Tensor_>
struct tensor_symmetry_assign_value
{
  typedef typename Tensor_::Index Index;
  typedef typename Tensor_::Scalar Scalar;
  constexpr static std::size_t NumIndices = Tensor_::NumIndices;

  static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transformation_flags, int dummy, Tensor_& tensor, const Scalar& value_)
  {
    Scalar value(value_);
    if (transformation_flags & ConjugationFlag)
      value = numext::conj(value);
    if (transformation_flags & NegationFlag)
      value = -value;
    tensor.coeffRef(transformed_indices) = value;
    return dummy;
  }
};

template<typename Tensor_>
struct tensor_symmetry_calculate_flags
{
  typedef typename Tensor_::Index Index;
  constexpr static std::size_t NumIndices = Tensor_::NumIndices;

  static inline int run(const std::array<Index, NumIndices>& transformed_indices, int transform_flags, int current_flags, const std::array<Index, NumIndices>& orig_indices)
  {
    if (transformed_indices == orig_indices) {
      if (transform_flags & (ConjugationFlag | NegationFlag))
        return current_flags | GlobalImagFlag; // anti-hermitian diagonal
      else if (transform_flags & ConjugationFlag)
        return current_flags | GlobalRealFlag; // hermitian diagonal
      else if (transform_flags & NegationFlag)
        return current_flags | GlobalZeroFlag; // anti-symmetric diagonal
    }
    return current_flags;
  }
};

template<typename Tensor_, typename Symmetry_, int Flags = 0>
class tensor_symmetry_value_setter
{
  public:
    typedef typename Tensor_::Index Index;
    typedef typename Tensor_::Scalar Scalar;
    constexpr static std::size_t NumIndices = Tensor_::NumIndices;

    inline tensor_symmetry_value_setter(Tensor_& tensor, Symmetry_ const& symmetry, std::array<Index, NumIndices> const& indices)
      : m_tensor(tensor), m_symmetry(symmetry), m_indices(indices) { }

    inline tensor_symmetry_value_setter<Tensor_, Symmetry_, Flags>& operator=(Scalar const& value)
    {
      doAssign(value);
      return *this;
    }
  private:
    Tensor_& m_tensor;
    Symmetry_ m_symmetry;
    std::array<Index, NumIndices> m_indices;

    inline void doAssign(Scalar const& value)
    {
      #ifdef EIGEN_TENSOR_SYMMETRY_CHECK_VALUES
        int value_flags = m_symmetry.template apply<internal::tensor_symmetry_calculate_flags<Tensor_>, int>(m_indices, m_symmetry.globalFlags(), m_indices);
        if (value_flags & GlobalRealFlag)
          eigen_assert(numext::imag(value) == 0);
        if (value_flags & GlobalImagFlag)
          eigen_assert(numext::real(value) == 0);
      #endif
      m_symmetry.template apply<internal::tensor_symmetry_assign_value<Tensor_>, int>(m_indices, 0, m_tensor, value);
    }
};

} // end namespace internal

} // end namespace Eigen

#endif // EIGEN_CXX11_TENSORSYMMETRY_SYMMETRY_H

/*
 * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
 */
