// 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/.
template<int One_, int Two_> struct Symmetry
{
static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
constexpr staticint One = One_;
constexpr staticint Two = Two_;
constexpr staticint Flags = 0;
};
template<int One_, int Two_> struct AntiSymmetry
{
static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
constexpr staticint One = One_;
constexpr staticint Two = Two_;
constexpr staticint Flags = NegationFlag;
};
template<int One_, int Two_> struct Hermiticity
{
static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
constexpr staticint One = One_;
constexpr staticint Two = Two_;
constexpr staticint Flags = ConjugationFlag;
};
template<int One_, int Two_> struct AntiHermiticity
{
static_assert(One_ != Two_, "Symmetries must cover distinct indices.");
constexpr staticint One = One_;
constexpr staticint Two = Two_;
constexpr staticint 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; typedeftypename internal::tensor_symmetry_pre_analysis<NumIndices, Gen...>::root_type Base;
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;
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.