1 #ifndef __DUNE_ACFEM_TENSORS_OPERATIONTRAITS_HH__
2 #define __DUNE_ACFEM_TENSORS_OPERATIONTRAITS_HH__
6 #include "../mpl/compare.hh"
7 #include "../expressions/storage.hh"
8 #include "../expressions/expressionoperations.hh"
9 #include "expressionoperations.hh"
10 #include "operations/einsum.hh"
11 #include "operations/product.hh"
12 #include "operations/restriction.hh"
13 #include "operations/transpose.hh"
34 template<std::size_t... Dims, std::size_t... PivotIndices>
37 static_assert(
sizeof...(Dims) ==
sizeof...(PivotIndices),
38 "Size of pivot indices must match size of co-dimension.");
41 using InvertibleOperation = void;
42 using OperationType = RestrictionOperation<
IndexSequence<Dims...>, PivotSequence>;
44 template<
class T,
class SFINAE =
void>
53 struct HasOperation<T, std::enable_if_t<(sizeof(decltype(restriction<Dims...>(std::declval<T>(), PivotSequence{}))) >= 0)> >
56 using ResultType = std::decay_t<decltype(restriction<Dims...>(std::declval<T>(), PivotSequence{}))>;
60 using ResultType =
typename HasOperation<T>::ResultType;
64 static constexpr
auto signPropagation(
const Sign&)
69 static std::string name()
71 return "rst<"+toString(IndexSequence<Dims...>{})+
"@"+toString(PivotSequence{})+
">";
75 static constexpr
auto polynomialOrder(Order oldOrder)
80 template<
class T,
class... Rest, std::enable_if_t<HasOperation<T>::value,
int> = 0>
81 auto operator()(T&& t, Rest&&...)
const
83 return restriction<Dims...>(std::forward<T>(t), PivotSequence{});
86 template<
class T,
class... Rest, std::enable_if_t<!HasOperation<T>::value,
int> = 0>
87 constexpr decltype(
auto) operator()(T&& t, Rest&&...)
const
89 return std::forward<T>(t);
92 using PivotType = PivotSequence;
93 PivotType pivotIndices_;
96 template<std::size_t... Dims>
100 using ThisType = OperationTraits;
102 using InvertibleOperation = void;
103 using OperationType = RestrictionOperation<
IndexSequence<Dims...>, IndexSequence<> >;
106 : pivotIndices_({{}})
109 OperationTraits(
const OperationTraits& other)
110 : pivotIndices_(other.pivotIndices_)
113 OperationTraits(OperationTraits&& other)
114 : pivotIndices_(std::move(other.pivotIndices_))
117 template<
class List, std::size_t... I, std::enable_if_t<IsTupleLike<List>::value,
int> = 0>
118 OperationTraits(
const List& l, IndexSequence<I...>)
119 : pivotIndices_({{ (IndexType)get<I>(l)... }})
122 template<class List, std::enable_if_t<IsTupleLike<List>::value,
int> = 0>
123 OperationTraits(
const List& l)
127 template<
class T, std::size_t N, std::size_t... I>
128 OperationTraits(
const T (&l)[N], IndexSequence<I...>)
129 : pivotIndices_({{ (IndexType)get<I>(l)... }})
132 template<
class I, std::
size_t N>
133 OperationTraits(
const I (&l)[N])
137 template<
class T,
class SFINAE =
void>
142 using ResultType = T;
146 struct HasOperation<T, std::enable_if_t<sizeof(decltype(restriction<Dims...>(std::declval<T>()))) >= 0> >
149 using ResultType = std::decay_t<decltype(restriction<Dims...>(std::declval<T>()))>;
153 using ResultType =
typename HasOperation<T>::ResultType;
157 static constexpr
auto signPropagation(
const Sign&)
162 std::string name()
const
164 return "rst<"+toString(IndexSequence<Dims...>{})+
"@["+toString(pivotIndices_)+
"]>";
167 template<
class Order>
168 static constexpr
auto polynomialOrder(Order oldOrder)
174 template<
class T,
class... Rest, std::enable_if_t<HasOperation<T>::value,
int> = 0>
175 constexpr
auto operator()(T&& t, Rest&&...)
const
177 return restriction<Dims...>(std::forward<T>(t), pivotIndices_);
180 template<
class T,
class... Rest, std::enable_if_t<!HasOperation<T>::value,
int> = 0>
181 constexpr decltype(
auto) operator()(T&& t, Rest&&...)
const
183 return std::forward<T>(t);
186 using IndexType = unsigned;
187 using PivotType = std::array<IndexType,
sizeof...(Dims)>;
188 PivotType pivotIndices_;
204 template<
class T,
class SFINAE =
void>
209 using ResultType = T;
213 struct HasOperation<T,
VoidType<decltype(
transpose(std::declval<T>(), Perm{}))> >
216 using ResultType = std::decay_t<decltype(transpose(std::declval<T>(), Perm{}))>;
221 static constexpr
auto signPropagation(
const Sign&)
226 static std::string name()
228 return "tr<"+toString(Perm{})+
">";
231 template<
class Order>
232 static constexpr
auto polynomialOrder(Order oldOrder)
238 auto operator()(T&& t)
const
240 return transpose(std::forward<T>(t), Perm{});
243 template<class T, std::enable_if_t<!HasOperation<T>::value,
int> = 0>
244 constexpr decltype(
auto) operator()(T&& t)
const
248 std::clog <<
"no transpose " << toString(Perm{}) <<
" for " << t.name() << std::endl;
252 return std::forward<T>(t);
265 using InvertibleOperation = void;
268 template<
class T,
class SFINAE =
void>
273 using ResultType = T;
277 struct HasOperation<T,
VoidType<decltype(reshape(std::declval<T>(), Sig{}))> >
280 using ResultType = std::decay_t<decltype(reshape(std::declval<T>(), Sig{}))>;
285 static constexpr
auto signPropagation(
const Sign&)
290 static std::string name()
292 return "reshape<"+toString(Sig{})+
">";
295 template<
class Order>
296 static constexpr
auto polynomialOrder(Order oldOrder)
302 auto operator()(T&& t)
const
304 return reshape(std::forward<T>(t), Sig{});
307 template<class T, std::enable_if_t<!HasOperation<T>::value,
int> = 0>
308 constexpr decltype(
auto) operator()(T&& t)
const
311 return std::forward<T>(t);
329 template<
class Pos1,
class Pos2,
class Dims>
333 "Number of contraction indices must coincide for Einstein-summation.");
335 using InvertibleOperation = void;
338 using LeftIndexPositions = Pos1;
339 using RightIndexPositions = Pos2;
340 using Dimensions = Dims;
342 template<
class T0,
class T1>
344 SequenceSliceComplement<typename TensorTraits<T1>::Signature, RightIndexPositions> >;
346 static constexpr Dimensions dimensions()
351 static constexpr std::size_t contractionDimension()
353 return prod(dimensions());
356 template<
class T1,
class T2,
class SFINAE =
void>
361 using ResultType = std::decay_t<decltype(std::declval<T1>() * std::declval<T2>())>;
364 template<
class T1,
class T2>
365 struct HasOperation<T1, T2,
VoidType<decltype(
einsum<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))> >
368 using ResultType = std::decay_t<decltype(einsum<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))>;
371 template<
class T1,
class T2>
372 using ResultType =
typename HasOperation<T1, T2>::ResultType;
374 template<
class Order1,
class Order2>
375 static constexpr
auto polynomialOrder(Order1 order1, Order2 order2)
377 return order1 + order2;
380 static constexpr std::size_t dim = Prod<Dims>::value;
384 template<
class S1,
class S2>
385 static constexpr
auto signPropagation(
const S1&,
const S2&)
390 S1::isNonSingular && S2::isNonSingular
392 (((S1::reference >= 0) && S1::isSemiPositive)
394 ((S1::reference <= 0) && S1::isSemiNegative))
396 (((S2::reference >= 0) && S2::isSemiPositive)
398 ((S2::reference <= 0) && S2::isSemiNegative))),
400 ((S1::reference*S2::reference >= 0)
402 ((S1::isSemiPositive && S2::isSemiPositive)
404 (S1::isSemiNegative && S2::isSemiNegative))),
406 ((S1::reference*S2::reference <= 0)
408 ((S1::isSemiPositive && S2::isSemiNegative)
410 (S1::isSemiNegative && S2::isSemiPositive))),
412 dim * S1::reference * S2::reference>{};
415 static std::string name()
417 return "*"+(
Pos1::size() > 0 ?
"["+toString(Pos1{})+
"]["+toString(Pos2{})+
"]" :
"");
420 template<class T1, class T2, std::enable_if_t<HasOperation<T1, T2>::value,
int> = 0>
421 constexpr
auto operator()(T1&& t1, T2&& t2)
const
423 return einsum<Pos1, Pos2>(std::forward<T1>(t1), std::forward<T2>(t2));
427 template<class T1, class T2, std::enable_if_t<!HasOperation<T1, T2>::value,
int> = 0>
428 constexpr
auto operator()(T1&& t1, T2&& t2)
const
430 return std::forward<T1>(t1) * std::forward<T2>(t2);
448 template<
class Pos1,
class Pos2,
class Dims>
452 "Number of contraction indices must coincide for product operation.");
454 using InvertibleOperation = void;
457 using LeftIndexPositions = Pos1;
458 using RightIndexPositions = Pos2;
459 using Dimensions = Dims;
461 template<
class T1,
class T2,
class SFINAE =
void>
466 using ResultType = std::decay_t<decltype(std::declval<T1>() * std::declval<T2>())>;
469 template<
class T1,
class T2>
470 struct HasOperation<T1, T2, std::enable_if_t<(sizeof(decltype(multiply<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))) >= 0)> >
473 using ResultType = std::decay_t<decltype(multiply<Pos1, Pos2>(std::declval<T1>(), std::declval<T2>()))>;
476 template<
class T1,
class T2>
477 using ResultType =
typename HasOperation<T1, T2>::ResultType;
479 template<
class Order1,
class Order2>
480 static constexpr
auto polynomialOrder(Order1 order1, Order2 order2)
482 return order1 + order2;
485 static constexpr std::size_t dim = 1;
489 template<
class S1,
class S2>
490 static constexpr
auto signPropagation(
const S1&,
const S2&)
495 S1::isNonSingular && S2::isNonSingular
497 (((S1::reference >= 0) && S1::isSemiPositive)
499 ((S1::reference <= 0) && S1::isSemiNegative))
501 (((S2::reference >= 0) && S2::isSemiPositive)
503 ((S2::reference <= 0) && S2::isSemiNegative))),
505 ((S1::reference*S2::reference >= 0)
507 ((S1::isSemiPositive && S2::isSemiPositive)
509 (S1::isSemiNegative && S2::isSemiNegative))),
511 ((S1::reference*S2::reference <= 0)
513 ((S1::isSemiPositive && S2::isSemiNegative)
515 (S1::isSemiNegative && S2::isSemiPositive))),
517 dim * S1::reference * S2::reference>{};
520 static std::string name()
522 return "."+(
Pos1::size() > 0 ?
"["+toString(Pos1{})+
"]["+toString(Pos2{})+
"]" :
"");
525 template<
class T1,
class T2>
526 auto operator()(T1&& t1, T2&& t2)
const
528 return multiply<Pos1, Pos2>(std::forward<T1>(t1), std::forward<T2>(t2));
532 template<class T1, class T2, std::enable_if_t<!HasOperation<T1, T2>::value,
int> = 0>
533 constexpr
auto operator()(T1&& t1, T2&& t2)
const
535 return std::forward<T1>(t1) * std::forward<T2>(t2);
540 struct SquareTraits<T, std::enable_if_t<(HasTensorTraitsV<T> && TensorTraits<T>::rank > 0)> >
542 using ExplodeFunctor = OperationTraits<
546 typename TensorTraits<T>::Signature>
551 struct SquareTraits<T, std::enable_if_t<(HasTensorTraitsV<T> && TensorTraits<T>::rank == 0)> >
553 using ExplodeFunctor = Tensor::ScalarEinsumFunctor;
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
auto restriction(T &&t, Indices &&indices, Seq< IndexPositions... >=Seq< IndexPositions... >{})
Generate a compile-time dynamic restriction with position given from a tuple-like object.
Definition: operandpromotion.hh:241
constexpr decltype(auto) einsum(T1 &&t1, T2 &&t2)
Tensor contraction for proper tensors.
Definition: einsum.hh:561
constexpr decltype(auto) transpose(T &&t, Seq< Perm... >=Seq< Perm... >{})
Promote operands to tensor transposition operation.
Definition: operandpromotion.hh:309
Sequence< std::size_t, V... > IndexSequence
Sequence of std::size_t values.
Definition: types.hh:64
typename MakeType< void, Other... >::Type VoidType
Generate void regardless of the template argument list.
Definition: types.hh:151
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
Einstein summation, i.e.
Definition: expressionoperations.hh:308
A class mainting the sign of an expression during operations.
Definition: sign.hh:30
std::true_type if F is an "elementary" scalar.
Definition: typetraits.hh:35
Signature of index positions of tensors.
Definition: expressionoperations.hh:232
Component-wise product over given index-set.
Definition: expressionoperations.hh:389
Permutation of index positions of tensors.
Definition: expressionoperations.hh:167