Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines metafunctions used by Tensor
6 :
7 : #pragma once
8 :
9 : #include <cstddef>
10 : #include <cstdint>
11 : #include <type_traits>
12 :
13 : #include "DataStructures/Tensor/IndexType.hpp"
14 : #include "Utilities/TMPL.hpp"
15 :
16 : /// \cond
17 : template <typename X, typename Symm, typename IndexList>
18 : class Tensor;
19 : /// \endcond
20 :
21 : /// \ingroup TensorGroup
22 : /// Contains all metafunctions related to Tensor manipulations
23 1 : namespace TensorMetafunctions {
24 : namespace detail {
25 : template <unsigned>
26 : struct check_index_symmetry_impl;
27 : // empty typelist or only had a vector to start with
28 : template <>
29 : struct check_index_symmetry_impl<0> {
30 : template <typename...>
31 : using f = std::true_type;
32 : };
33 :
34 : // found incorrect symmetric index
35 : template <>
36 : struct check_index_symmetry_impl<1> {
37 : template <typename...>
38 : using f = std::false_type;
39 : };
40 :
41 : // recurse the list
42 : template <>
43 : struct check_index_symmetry_impl<2> {
44 : template <typename Symm, typename IndexSymm, typename Index0,
45 : typename... IndexPack>
46 : using f = typename check_index_symmetry_impl<
47 : tmpl::has_key<IndexSymm, tmpl::front<Symm>>::value and
48 : not std::is_same<Index0,
49 : tmpl::at<IndexSymm, tmpl::front<Symm>>>::value
50 : ? 1
51 : : tmpl::size<Symm>::value == 1 ? 0 : 2>::
52 : template f<tmpl::pop_front<Symm>,
53 : tmpl::insert<IndexSymm, tmpl::pair<tmpl::front<Symm>, Index0>>,
54 : IndexPack...>;
55 : };
56 : } // namespace detail
57 :
58 : /*!
59 : * \ingroup TensorGroup
60 : * \brief Check that each of symmetric indices is in the same frame and have the
61 : * same dimensionality.
62 : */
63 : template <typename Symm, typename... IndexPack>
64 1 : using check_index_symmetry = typename detail::check_index_symmetry_impl<
65 : tmpl::size<Symm>::value == 0 or tmpl::size<Symm>::value == 1 ? 0 : 2>::
66 : template f<Symm, tmpl::map<>, IndexPack...>;
67 : template <typename Symm, typename... IndexPack>
68 0 : constexpr bool check_index_symmetry_v =
69 : check_index_symmetry<Symm, IndexPack...>::value;
70 :
71 : /*!
72 : * \ingroup TensorGroup
73 : * \brief Add a spatial index to the front of a Tensor
74 : *
75 : * \tparam Tensor the tensor type to which the new index is prepended
76 : * \tparam VolumeDim the volume dimension of the tensor index to prepend
77 : * \tparam Fr the ::Frame of the tensor index to prepend
78 : */
79 : template <typename Tensor, std::size_t VolumeDim, UpLo Ul,
80 : typename Fr = Frame::Grid>
81 1 : using prepend_spatial_index = ::Tensor<
82 : typename Tensor::type,
83 : tmpl::push_front<
84 : typename Tensor::symmetry,
85 : tmpl::int32_t<
86 : 1 + tmpl::fold<typename Tensor::symmetry, tmpl::int32_t<0>,
87 : tmpl::max<tmpl::_state, tmpl::_element>>::value>>,
88 : tmpl::push_front<typename Tensor::index_list,
89 : SpatialIndex<VolumeDim, Ul, Fr>>>;
90 :
91 : /*!
92 : * \ingroup TensorGroup
93 : * \brief Add a spacetime index to the front of a Tensor
94 : *
95 : * \tparam Tensor the tensor type to which the new index is prepended
96 : * \tparam VolumeDim the volume dimension of the tensor index to prepend
97 : * \tparam Fr the ::Frame of the tensor index to prepend
98 : */
99 : template <typename Tensor, std::size_t VolumeDim, UpLo Ul,
100 : typename Fr = Frame::Grid>
101 1 : using prepend_spacetime_index = ::Tensor<
102 : typename Tensor::type,
103 : tmpl::push_front<
104 : typename Tensor::symmetry,
105 : tmpl::int32_t<
106 : 1 + tmpl::fold<typename Tensor::symmetry, tmpl::int32_t<0>,
107 : tmpl::max<tmpl::_state, tmpl::_element>>::value>>,
108 : tmpl::push_front<typename Tensor::index_list,
109 : SpacetimeIndex<VolumeDim, Ul, Fr>>>;
110 :
111 : /// \ingroup TensorGroup
112 : /// \brief remove the first index of a tensor
113 : /// \tparam Tensor the tensor type whose first index is removed
114 : template <typename Tensor>
115 1 : using remove_first_index =
116 : ::Tensor<typename Tensor::type, tmpl::pop_front<typename Tensor::symmetry>,
117 : tmpl::pop_front<typename Tensor::index_list>>;
118 :
119 : /// \ingroup TensorGroup
120 : /// \brief Swap the valences of all indices on a Tensor
121 : template <typename Tensor>
122 1 : using change_all_valences =
123 : ::Tensor<typename Tensor::type, typename Tensor::symmetry,
124 : tmpl::transform<typename Tensor::index_list,
125 : tmpl::bind<change_index_up_lo, tmpl::_1>>>;
126 :
127 : /// \ingroup TensorGroup
128 : /// \brief Swap the data type of a tensor for a new type
129 : /// \tparam NewType the new data type
130 : /// \tparam Tensor the tensor from which to keep symmetry and index information
131 : template <typename NewType, typename Tensor>
132 1 : using swap_type =
133 : ::Tensor<NewType, typename Tensor::symmetry, typename Tensor::index_list>;
134 :
135 : namespace detail {
136 : template <typename T, typename Frame>
137 : using frame_is_the_same = std::is_same<typename T::Frame, Frame>;
138 : } // namespace detail
139 :
140 : /// \ingroup TensorGroup
141 : /// \brief Return tmpl::true_type if any indices of the Tensor are in the
142 : /// frame Frame.
143 : template <typename Tensor, typename Frame>
144 1 : using any_index_in_frame =
145 : tmpl::any<typename Tensor::index_list,
146 : tmpl::bind<detail::frame_is_the_same, tmpl::_1, Frame>>;
147 :
148 : /// \ingroup TensorGroup
149 : /// \brief Return true if any indices of the Tensor are in the
150 : /// frame Frame.
151 : template <typename Tensor, typename Frame>
152 1 : constexpr bool any_index_in_frame_v = any_index_in_frame<Tensor, Frame>::value;
153 :
154 : } // namespace TensorMetafunctions
|