12b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This file is part of Eigen, a lightweight C++ template library
22b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// for linear algebra.
32b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang//
42b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Copyright (C) 2013 Christian Seiler <christian@iwakd.de>
52b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang//
62b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// This Source Code Form is subject to the terms of the Mozilla
72b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// Public License v. 2.0. If a copy of the MPL was not distributed
82b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
92b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#ifndef EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#define EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangnamespace Eigen {
142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangclass DynamicSGroup
162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{
172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  public:
182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline explicit DynamicSGroup() : m_numIndices(1), m_elements(), m_generators(), m_globalFlags(0) { m_elements.push_back(ge(Generator(0, 0, 0))); }
192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroup(const DynamicSGroup& o) : m_numIndices(o.m_numIndices), m_elements(o.m_elements), m_generators(o.m_generators), m_globalFlags(o.m_globalFlags) { }
202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroup(DynamicSGroup&& o) : m_numIndices(o.m_numIndices), m_elements(), m_generators(o.m_generators), m_globalFlags(o.m_globalFlags) { std::swap(m_elements, o.m_elements); }
212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroup& operator=(const DynamicSGroup& o) { m_numIndices = o.m_numIndices; m_elements = o.m_elements; m_generators = o.m_generators; m_globalFlags = o.m_globalFlags; return *this; }
222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroup& operator=(DynamicSGroup&& o) { m_numIndices = o.m_numIndices; std::swap(m_elements, o.m_elements); m_generators = o.m_generators; m_globalFlags = o.m_globalFlags; return *this; }
232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    void add(int one, int two, int flags = 0);
252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Gen_>
272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void add(Gen_) { add(Gen_::One, Gen_::Two, Gen_::Flags); }
282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void addSymmetry(int one, int two) { add(one, two, 0); }
292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void addAntiSymmetry(int one, int two) { add(one, two, NegationFlag); }
302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void addHermiticity(int one, int two) { add(one, two, ConjugationFlag); }
312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void addAntiHermiticity(int one, int two) { add(one, two, NegationFlag | ConjugationFlag); }
322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Op, typename RV, typename Index, std::size_t N, typename... Args>
342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline RV apply(const std::array<Index, N>& idx, RV initial, Args&&... args) const
352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      eigen_assert(N >= m_numIndices && "Can only apply symmetry group to objects that have at least the required amount of indices.");
372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (std::size_t i = 0; i < size(); i++)
382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        initial = Op::run(h_permute(i, idx, typename internal::gen_numeric_list<int, N>::type()), m_elements[i].flags, initial, std::forward<Args>(args)...);
392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return initial;
402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Op, typename RV, typename Index, typename... Args>
432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline RV apply(const std::vector<Index>& idx, RV initial, Args&&... args) const
442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      eigen_assert(idx.size() >= m_numIndices && "Can only apply symmetry group to objects that have at least the required amount of indices.");
462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (std::size_t i = 0; i < size(); i++)
472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        initial = Op::run(h_permute(i, idx), m_elements[i].flags, initial, std::forward<Args>(args)...);
482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return initial;
492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline int globalFlags() const { return m_globalFlags; }
522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline std::size_t size() const { return m_elements.size(); }
532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Tensor_, typename... IndexTypes>
552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup> operator()(Tensor_& tensor, typename Tensor_::Index firstIndex, IndexTypes... otherIndices) const
562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      static_assert(sizeof...(otherIndices) + 1 == Tensor_::NumIndices, "Number of indices used to access a tensor coefficient must be equal to the rank of the tensor.");
582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return operator()(tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices>{{firstIndex, otherIndices...}});
592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Tensor_>
622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup> operator()(Tensor_& tensor, std::array<typename Tensor_::Index, Tensor_::NumIndices> const& indices) const
632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return internal::tensor_symmetry_value_setter<Tensor_, DynamicSGroup>(tensor, *this, indices);
652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  private:
672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    struct GroupElement {
682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      std::vector<int> representation;
692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      int flags;
702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      bool isId() const
712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      {
722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (std::size_t i = 0; i < representation.size(); i++)
732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          if (i != (size_t)representation[i])
742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang            return false;
752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        return true;
762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    };
782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    struct Generator {
792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      int one;
802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      int two;
812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      int flags;
822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      constexpr inline Generator(int one_, int two_, int flags_) : one(one_), two(two_), flags(flags_) {}
832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    };
842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    std::size_t m_numIndices;
862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    std::vector<GroupElement> m_elements;
872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    std::vector<Generator> m_generators;
882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    int m_globalFlags;
892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Index, std::size_t N, int... n>
912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline std::array<Index, N> h_permute(std::size_t which, const std::array<Index, N>& idx, internal::numeric_list<int, n...>) const
922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return std::array<Index, N>{{ idx[n >= m_numIndices ? n : m_elements[which].representation[n]]... }};
942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Index>
972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline std::vector<Index> h_permute(std::size_t which, std::vector<Index> idx) const
982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      std::vector<Index> result;
1002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      result.reserve(idx.size());
1012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (auto k : m_elements[which].representation)
1022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        result.push_back(idx[k]);
1032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (std::size_t i = m_numIndices; i < idx.size(); i++)
1042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        result.push_back(idx[i]);
1052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return result;
1062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline GroupElement ge(Generator const& g) const
1092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      GroupElement result;
1112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      result.representation.reserve(m_numIndices);
1122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      result.flags = g.flags;
1132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (std::size_t k = 0; k < m_numIndices; k++) {
1142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        if (k == (std::size_t)g.one)
1152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          result.representation.push_back(g.two);
1162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        else if (k == (std::size_t)g.two)
1172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          result.representation.push_back(g.one);
1182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        else
1192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          result.representation.push_back(int(k));
1202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
1212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return result;
1222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    GroupElement mul(GroupElement, GroupElement) const;
1252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline GroupElement mul(Generator g1, GroupElement g2) const
1262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return mul(ge(g1), g2);
1282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline GroupElement mul(GroupElement g1, Generator g2) const
1312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return mul(g1, ge(g2));
1332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline GroupElement mul(Generator g1, Generator g2) const
1362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return mul(ge(g1), ge(g2));
1382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline int findElement(GroupElement e) const
1412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (auto ee : m_elements) {
1432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        if (ee.representation == e.representation)
1442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          return ee.flags ^ e.flags;
1452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
1462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      return -1;
1472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    void updateGlobalFlags(int flagDiffOfSameGenerator);
1502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang};
1512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang// dynamic symmetry group that auto-adds the template parameters in the constructor
1532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangtemplate<typename... Gen>
1542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wangclass DynamicSGroupFromTemplateArgs : public DynamicSGroup
1552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{
1562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  public:
1572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroupFromTemplateArgs() : DynamicSGroup()
1582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      add_all(internal::type_list<Gen...>());
1602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroupFromTemplateArgs(DynamicSGroupFromTemplateArgs const& other) : DynamicSGroup(other) { }
1622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroupFromTemplateArgs(DynamicSGroupFromTemplateArgs&& other) : DynamicSGroup(other) { }
1632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroupFromTemplateArgs<Gen...>& operator=(const DynamicSGroupFromTemplateArgs<Gen...>& o) { DynamicSGroup::operator=(o); return *this; }
1642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline DynamicSGroupFromTemplateArgs<Gen...>& operator=(DynamicSGroupFromTemplateArgs<Gen...>&& o) { DynamicSGroup::operator=(o); return *this; }
1652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  private:
1672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    template<typename Gen1, typename... GenNext>
1682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void add_all(internal::type_list<Gen1, GenNext...>)
1692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      add(Gen1());
1712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      add_all(internal::type_list<GenNext...>());
1722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    inline void add_all(internal::type_list<>)
1752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    {
1762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
1772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang};
1782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wanginline DynamicSGroup::GroupElement DynamicSGroup::mul(GroupElement g1, GroupElement g2) const
1802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{
1812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  eigen_internal_assert(g1.representation.size() == m_numIndices);
1822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  eigen_internal_assert(g2.representation.size() == m_numIndices);
1832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  GroupElement result;
1852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result.representation.reserve(m_numIndices);
1862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (std::size_t i = 0; i < m_numIndices; i++) {
1872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    int v = g2.representation[g1.representation[i]];
1882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    eigen_assert(v >= 0);
1892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    result.representation.push_back(v);
1902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
1912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  result.flags = g1.flags ^ g2.flags;
1922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  return result;
1932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
1942b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
1952b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wanginline void DynamicSGroup::add(int one, int two, int flags)
1962b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{
1972b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  eigen_assert(one >= 0);
1982b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  eigen_assert(two >= 0);
1992b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  eigen_assert(one != two);
2002b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2012b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  if ((std::size_t)one >= m_numIndices || (std::size_t)two >= m_numIndices) {
2022b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    std::size_t newNumIndices = (one > two) ? one : two + 1;
2032b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (auto& gelem : m_elements) {
2042b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      gelem.representation.reserve(newNumIndices);
2052b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      for (std::size_t i = m_numIndices; i < newNumIndices; i++)
2062b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        gelem.representation.push_back(i);
2072b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2082b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    m_numIndices = newNumIndices;
2092b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2102b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2112b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  Generator g{one, two, flags};
2122b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  GroupElement e = ge(g);
2132b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2142b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  /* special case for first generator */
2152b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  if (m_elements.size() == 1) {
2162b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    while (!e.isId()) {
2172b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      m_elements.push_back(e);
2182b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      e = mul(e, g);
2192b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2202b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2212b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    if (e.flags > 0)
2222b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      updateGlobalFlags(e.flags);
2232b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2242b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    // only add in case we didn't have identity
2252b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    if (m_elements.size() > 1)
2262b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      m_generators.push_back(g);
2272b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    return;
2282b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2292b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2302b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  int p = findElement(e);
2312b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  if (p >= 0) {
2322b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    updateGlobalFlags(p);
2332b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    return;
2342b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  }
2352b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2362b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  std::size_t coset_order = m_elements.size();
2372b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  m_elements.push_back(e);
2382b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  for (std::size_t i = 1; i < coset_order; i++)
2392b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    m_elements.push_back(mul(m_elements[i], e));
2402b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  m_generators.push_back(g);
2412b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2422b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  std::size_t coset_rep = coset_order;
2432b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  do {
2442b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    for (auto g : m_generators) {
2452b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      e = mul(m_elements[coset_rep], g);
2462b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      p = findElement(e);
2472b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      if (p < 0) {
2482b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        // element not yet in group
2492b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        m_elements.push_back(e);
2502b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        for (std::size_t i = 1; i < coset_order; i++)
2512b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang          m_elements.push_back(mul(m_elements[i], e));
2522b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      } else if (p > 0) {
2532b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        updateGlobalFlags(p);
2542b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      }
2552b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2562b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    coset_rep += coset_order;
2572b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang  } while (coset_rep < m_elements.size());
2582b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
2592b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2602b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wanginline void DynamicSGroup::updateGlobalFlags(int flagDiffOfSameGenerator)
2612b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang{
2622b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    switch (flagDiffOfSameGenerator) {
2632b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      case 0:
2642b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      default:
2652b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        // nothing happened
2662b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        break;
2672b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      case NegationFlag:
2682b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        // every element is it's own negative => whole tensor is zero
2692b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        m_globalFlags |= GlobalZeroFlag;
2702b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        break;
2712b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      case ConjugationFlag:
2722b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        // every element is it's own conjugate => whole tensor is real
2732b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        m_globalFlags |= GlobalRealFlag;
2742b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        break;
2752b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      case (NegationFlag | ConjugationFlag):
2762b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        // every element is it's own negative conjugate => whole tensor is imaginary
2772b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        m_globalFlags |= GlobalImagFlag;
2782b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang        break;
2792b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang      /* NOTE:
2802b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang       *   since GlobalZeroFlag == GlobalRealFlag | GlobalImagFlag, if one generator
2812b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang       *   causes the tensor to be real and the next one to be imaginary, this will
2822b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang       *   trivially give the correct result
2832b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang       */
2842b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang    }
2852b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang}
2862b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2872b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang} // end namespace Eigen
2882b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2892b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang#endif // EIGEN_CXX11_TENSORSYMMETRY_DYNAMICSYMMETRY_H
2902b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang
2912b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang/*
2922b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang * kate: space-indent on; indent-width 2; mixedindent off; indent-mode cstyle;
2932b8756b6f1de65d3f8bffab45be6c44ceb7411fcMiao Wang */
294