1#ifndef __DUNE_ACFEM_TENSORS_MODULES_KRONECKER_HH__ 
    2#define __DUNE_ACFEM_TENSORS_MODULES_KRONECKER_HH__ 
    4#include "../../mpl/assign.hh" 
    5#include "../tensorbase.hh" 
    6#include "../expressiontraits.hh" 
   22      template<
class Signature, 
class PivotIndices, 
class Field>
 
   25      template<
class Signature, 
class PivotIndices, 
class Field>
 
   26      struct HasSpecializedExpressionTraits<KroneckerDelta<Signature, PivotIndices, Field> >
 
   33      template<
class Field, std::size_t... Dimensions, std::size_t... PivotIndices>
 
   34      class KroneckerDelta<Seq<Dimensions...>, Seq<PivotIndices...>, Field>
 
   35        : 
public TensorBase<FloatingPointClosure<Field>, Seq<Dimensions...>, KroneckerDelta<Seq<Dimensions...>, Seq<PivotIndices...>, Field> >
 
   37        , 
public MPL::UniqueTags<ConstantExpression,
 
   38                                 ConditionalType<IsTypedValue<Field>::value, TypedValueExpression, void> >
 
   43        using typename BaseType::Signature;
 
   44        using typename BaseType::FieldType;
 
   45        using PivotSequence = Seq<PivotIndices...>;
 
   46        using ValueType = Field;
 
   51        template<
class... Dims,
 
   52                 std::enable_if_t<(
sizeof...(Dims) == rank
 
   58          if (std::make_tuple((std::size_t)indices...) != std::make_tuple(PivotIndices...)) {
 
   61            return FieldType(ValueType{});
 
   68        template<std::size_t... Indices,
 
   69                 std::enable_if_t<
sizeof...(Indices) == rank, 
int> = 0>
 
   72          using ReturnType = ConditionalType<isZero<Indices...>(),
 
   81        template<std::size_t... Indices, std::size_t... Pos>
 
   82        static bool constexpr isZeroExpander(Seq<Indices...>, Seq<Pos...>)
 
   84          return !(... && (Indices == 
Get<Pos, Seq<PivotIndices...> >::value));
 
   88        template<std::size_t... Indices, 
class Pos = 
MakeIndexSequence<
sizeof...(Indices)> >
 
   89        static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
 
   92          using RealPos = 
HeadPart<
sizeof...(Indices), Pos>;
 
   94          return isZeroExpander(Seq<Indices...>{}, RealPos{});
 
   97        std::string name()
 const 
   99          return "delta<"+toString(Signature{})+
"@["+toString(PivotSequence{})+
"]>";
 
  102        static constexpr auto lookAt()
 
  104          return PivotSequence{};
 
  111      template<
class Field, std::size_t D0, std::size_t... RestDims>
 
  112      class KroneckerDelta<Seq<D0, RestDims...>, Seq<>, Field>
 
  113        : 
public TensorBase<FloatingPointClosure<Field>, Seq<D0, RestDims...>, KroneckerDelta<Seq<D0, RestDims...>, Seq<>, Field> >
 
  119        using BaseType::rank;
 
  120        using typename BaseType::Signature;
 
  121        using typename BaseType::FieldType;
 
  122        using ValueType = Field;
 
  126        template<std::size_t... I, 
class T>
 
  127        KroneckerDelta(T&& tuple, Seq<I...>&&)
 
  128          : pivotIndices_({{ (std::size_t)std::get<I>(tuple)... }})
 
  156        template<
class... Indices,
 
  157                 std::enable_if_t<(
sizeof...(Indices) != 0
 
  159                                   sizeof...(Indices) == rank
 
  164          : pivotIndices_({{ (std::size_t)indices... }})
 
  170        template<
class... Dims,
 
  171                 std::enable_if_t<(
sizeof...(Dims) == rank
 
  177          if (std::array<std::size_t, rank>({{ (std::size_t)indices... }}) != pivotIndices_) {
 
  180            return FieldType(ValueType{});
 
  189        template<std::size_t... Indices,
 
  190                 std::enable_if_t<
sizeof...(Indices) == rank, 
int> = 0>
 
  193          return (*
this)(Indices...);
 
  196        template<std::size_t... Indices, 
class Pos = 
MakeIndexSequence<
sizeof...(Indices)> >
 
  197        static bool constexpr isZero(Seq<Indices...> = Seq<Indices...>{}, Pos = Pos{})
 
  206        template<
class... Indices,
 
  207                 std::enable_if_t<((
sizeof...(Indices) > 0)
 
  212          static_assert(
sizeof...(Indices) == rank,
 
  213                        "The number of pivot indices must match the co-dimension.");
 
  214          pivotIndices_ = {{ (std::size_t)indices... }};
 
  227          static_assert(size<T>() == rank,
 
  228                        "The number of pivot indices must match the co-dimension.");
 
  233        const std::array<std::size_t, rank>& 
lookAt() const&
 
  235          return pivotIndices_;
 
  238        std::string name()
 const 
  240          return "delta<"+toString(Signature{})+
"@["+toString(pivotIndices_)+
"]>";
 
  244        std::array<std::size_t, rank> pivotIndices_;
 
  248      template<
class T, 
class SFINAE = 
void>
 
  258      template<std::size_t... Pos, 
class PivotIndices, 
class Field>
 
  259      struct IsKroneckerDelta<KroneckerDelta<Seq<Pos...>, PivotIndices, Field> >
 
  264      struct IsConstKroneckerDelta
 
  269      struct IsConstKroneckerDelta<T&>
 
  270        : IsConstKroneckerDelta<std::decay_t<T> >
 
  274      struct IsConstKroneckerDelta<T&&>
 
  275        : IsConstKroneckerDelta<std::decay_t<T> >
 
  281      template<std::size_t... Pos, std::size_t... Pivot, 
class Field>
 
  282      struct IsConstKroneckerDelta<KroneckerDelta<Seq<Pos...>, Seq<Pivot...>, Field> >
 
  287      struct IsDiagonalKroneckerDelta
 
  292      struct IsDiagonalKroneckerDelta<T&>
 
  293        : IsDiagonalKroneckerDelta<T>
 
  297      struct IsDiagonalKroneckerDelta<T&&>
 
  298        : IsDiagonalKroneckerDelta<T>
 
  301      template<std::size_t... Pos, std::size_t Pivot0, std::size_t... Pivot, 
class Field>
 
  302      struct IsDiagonalKroneckerDelta<KroneckerDelta<Seq<Pos...>, Seq<Pivot0, Pivot...>, Field> >
 
  307      using PivotSequence = 
typename std::decay_t<T>::PivotSequence;
 
  309      template<std::size_t... Index, 
class Dims, 
class F = Expressions::Closure,
 
  310               std::enable_if_t<IsSequence<Dims>::value, 
int> = 0>
 
  311      auto kroneckerDelta(Dims = Dims{}, Seq<Index...> = Seq<Index...>{}, F closure = F{})
 
  313        static_assert(
Dims::size() == 
sizeof...(Index),
 
  314                      "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
 
  315        static_assert(Seq<Index...>{} < Dims{},
 
  316                      "Index tuple not in range of tensor dimensions");
 
  318        return closure(KroneckerDelta<Dims, Seq<Index...>, IntFraction<1> >{});
 
  321      template<std::size_t... Dimensions, std::size_t... Index, 
class F = Expressions::Closure>
 
  322      auto kroneckerDelta(Seq<Dimensions...>, Seq<Index...>, F closure = F{})
 
  324        static_assert(
sizeof...(Dimensions) == 
sizeof...(Index),
 
  325                      "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
 
  326        static_assert(Seq<Index...>{} < Seq<Dimensions...>{},
 
  327                      "Index tuple not in range of tensor dimensions");
 
  329        return closure(KroneckerDelta<Seq<Dimensions...>, Seq<Index...>, IntFraction<1> >{});
 
  332      template<
class T, std::size_t... Index, 
class F = Expressions::Closure,
 
  333               std::enable_if_t<IsTensorOperand<T>::value, 
int> = 0>
 
  334      auto kroneckerDelta(T&&, Seq<Index...>, F = F{})
 
  336        return kroneckerDelta(
typename TensorTraits<T>::Signature{}, Seq<Index...>{}, F{});
 
  339      template<std::size_t... Dimensions, 
class Tuple, 
class F = Expressions::Closure,
 
  340               std::enable_if_t<IsTupleLike<Tuple>::value, 
int> = 0>
 
  341      auto kroneckerDelta(Seq<Dimensions...>, 
const Tuple& tuple, F closure = F{})
 
  343        static_assert(
sizeof...(Dimensions) == size<Tuple>(),
 
  344                      "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
 
  345        return closure(KroneckerDelta<Seq<Dimensions...>, Seq<>, IntFraction<1> >(tuple));
 
  348      template<std::size_t... Dimensions, 
class... Indices,
 
  350      auto kroneckerDelta(Seq<Dimensions...>, Indices... indices)
 
  352        static_assert(
sizeof...(Dimensions) == 
sizeof...(Indices),
 
  353                      "Kronecker-Delta needs an index tuple of the size of the rank of the tensor.");
 
  354        return expressionClosure(KroneckerDelta<Seq<Dimensions...>, Seq<>, IntFraction<1> >(indices...));
 
  363    using Tensor::kroneckerDelta;
 
  365    template<
class Field, 
class Signature, 
class Indices>
 
  366    struct ExpressionTraits<Tensor::KroneckerDelta<Signature, Indices, Field> >
 
  367      : ExpressionTraits<Field>
 
  370      using BaseType = ExpressionTraits<Field>;
 
  372      using ExpressionType = Tensor::KroneckerDelta<Signature, Indices, Field>;
 
  373      static constexpr bool isOne = BaseType::isOne && ExpressionType::rank == 0;
 
  374      static constexpr bool isMinusOne = BaseType::isMinusOne && ExpressionType::rank == 0;
 
  375      static constexpr bool isNonZero = BaseType::isNonZero && ExpressionType::rank == 0;
 
  376      static constexpr bool isPositive = BaseType::isPositive && ExpressionType::rank == 0;
 
  377      static constexpr bool isNegative = BaseType::isNegative && ExpressionType::rank == 0;
 
  378      static constexpr bool isNonSingular = ExpressionType::rank == 0;
 
  379      using Sign = ExpressionSign<isNonZero, BaseType::isSemiPositive, BaseType::isSemiNegative>;
 
  381      static constexpr bool isIndependent = BaseType::isIndependent;
 
  383      static constexpr bool isTypedValue = BaseType::isTypedValue && !std::is_same<Indices, Tensor::Seq<> >::value;
 
  386    namespace Expressions {
 
  388      template<
class Field, 
class Signature, std::size_t Pivot0, std::size_t... Pivot>
 
  389      constexpr inline std::size_t 
WeightV<Tensor::KroneckerDelta<Signature, Tensor::Seq<Pivot0, Pivot...>, Field> > = (Pivot0 + ... + Pivot) + 1000*(... && (Pivot0 != Pivot));
 
  395  template<
class Field, 
class Signature, 
class Indices>
 
  396  struct FieldTraits<ACFem::Tensor::KroneckerDelta<Signature, Indices, Field> >
 
  397    : FieldTraits<std::decay_t<Field> >
 
KroneckerDelta(Indices... indices)
Constructor from a given index pack of lookAt() indices.
Definition: kronecker.hh:163
 
decltype(auto) operator()(Seq< Indices... >) const
Constant access from index-sequence.
Definition: kronecker.hh:191
 
FieldType operator()(Dims... indices) const
Insert the current view-indices at their proper positions and foward to the underlying "host" tensor.
Definition: kronecker.hh:175
 
KroneckerDelta(T &&tuple)
Constructor from a given tuple-like index collection.
Definition: kronecker.hh:145
 
void lookAt(Indices... indices)
"Move" the view to the given index pack.
Definition: kronecker.hh:210
 
void lookAt(T &&tuple)
"Move" pivot index to the specified values.
Definition: kronecker.hh:225
 
const std::array< std::size_t, rank > & lookAt() const &
Return the array of indices currently looking at.
Definition: kronecker.hh:233
 
FieldType operator()(Dims... indices) const
Compare the provided indices with the pivot sequence and return the result of the comparison.
Definition: kronecker.hh:56
 
decltype(auto) operator()(Seq< Indices... >) const
Constant access from index-sequence.
Definition: kronecker.hh:70
 
constexpr decltype(auto) expressionClosure(T &&t)
Do-nothing default implementation for pathologic cases.
Definition: interface.hh:93
 
decltype(operate(std::declval< OptOrF >(), std::declval< Rest >()...)) ExpressionType
Generate the type of an expression by calling operate().
Definition: optimizationbase.hh:256
 
constexpr std::size_t WeightV
Provide an overridable weight for expressions which defaults to their depth.
Definition: weight.hh:14
 
BoolConstant< ExpressionTraits< T >::isTypedValue > IsTypedValue
Compile-time true if T is a "typed value", e.g. a std::integral_constant.
Definition: expressiontraits.hh:90
 
auto & assign(T1 &t1, T2 &&t2)
Assign one tuple-alike to another by looping over the elements.
Definition: assign.hh:40
 
typename GetHeadPartHelper< Cnt, Seq >::Type HeadPart
Extract Cnt many consecutive elements from the front of Seq.
Definition: access.hh:217
 
constexpr std::size_t size()
Gives the number of elements in tuple-likes and std::integer_sequence.
Definition: size.hh:73
 
MakeIndexSequence< size< T >()> MakeSequenceFor
Make a simple index sequence of the size of the argument, which may be anything for which size<T>() e...
Definition: generators.hh:41
 
MakeSequence< std::size_t, N, Offset, Stride, Repeat > MakeIndexSequence
Make a sequence of std::size_t elements.
Definition: generators.hh:34
 
decltype(isIntegralTuple(std::declval< T >())) IsIntegralTuple
Decide whether the given tuple contains only integral types.
Definition: compare.hh:402
 
constexpr bool isConstant(Sequence< T, T0, Ts... >)
Definition: compare.hh:285
 
decltype(isIntegralPack(std::declval< T >()...)) IsIntegralPack
Decide whether the given parameter pack contains only integral types.
Definition: compare.hh:377
 
Constant< bool, V > BoolConstant
Short-cut for integral constant of type bool.
Definition: types.hh:48
 
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
 
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
 
A constant.
Definition: tags.hh:93
 
Terminals may derive from this class to express that they are expressions.
Definition: terminal.hh:25
 
Gets the type of the n-th element of a tuple-like or the std::integral_constant corresponding to the ...
Definition: access.hh:42
 
Traits in order to identify a Projection class.
Definition: kronecker.hh:251
 
Base class for all tensors.
Definition: tensorbase.hh:144
 
A terminal expression is an "expression end-point", i.e.
Definition: tags.hh:48