Xped
Loading...
Searching...
No Matches
TensorInterface_Array_impl.hpp
Go to the documentation of this file.
1#ifndef TENSOR_INTERFACE_ARRAY_IMPL_H_
2#define TENSOR_INTERFACE_ARRAY_IMPL_H_
3
4#include <array.h>
5#include <ein_reduce.h>
6
7#include "Xped/Util/Mpi.hpp"
9
10namespace Xped {
11
12namespace util {
13
14template <typename T, T... Nums>
15void print(seq::iseq<T, Nums...> seq)
16{
17 std::array<T, sizeof...(Nums)> s = {Nums...};
18 std::cout << "seq=";
19 for(auto x : s) { std::cout << x << " "; }
20 std::cout << std::endl;
21}
22
23} // namespace util
24
25template <typename Index, Index oldVal, Index newVal, typename S>
26using seq_replace = seq::insert<seq::index_of<oldVal, S>, newVal, seq::remove<oldVal, S>>;
27
29{
30 template <typename element_t, std::size_t N, size_t... Is>
31 static nda::internal::tuple_of_n<element_t, N> as_tuple(std::array<element_t, N> const& arr, std::index_sequence<Is...>)
32 {
33 return std::make_tuple(arr[Is]...);
34 }
35
36 template <typename element_t, std::size_t N>
37 static nda::internal::tuple_of_n<element_t, N> as_tuple(std::array<element_t, N> const& arr)
38 {
39 return as_tuple(arr, std::make_index_sequence<N>{});
40 }
41
42 // typedefs
43 template <typename Scalar, std::size_t Rank>
44 using TType = nda::dense_array<Scalar, Rank>;
45 template <typename Scalar, std::size_t Rank>
46 using cTType = const nda::dense_array<Scalar, Rank>;
47
48 template <typename Scalar, std::size_t Rank>
49 using MapTType = nda::dense_array_ref<Scalar, Rank>;
50 template <typename Scalar, std::size_t Rank>
51 using cMapTType = nda::const_dense_array_ref<Scalar, Rank>;
52
53 // template<typename Scalar, std::size_t Rank> using Indextype = typename nda::dense_array<Scalar,Rank>::shape_type::index_type;
54 using Indextype = nda::index_t;
55
56 // constructors
57 template <typename Scalar, std::size_t Rank>
58 static TType<Scalar, Rank> construct(const std::array<Indextype, Rank>& dims, mpi::XpedWorld& world = mpi::getUniverse())
59 {
60 return TType<Scalar, Rank>(as_tuple(dims));
61 }
62
63 template <typename Scalar, std::size_t Rank>
65 {
66 TType<Scalar, Rank> out(map.shape());
67 nda::copy(map, out);
68 return out;
69 }
70
71 template <typename Scalar, std::size_t Rank>
73 {
74 TType<Scalar, Rank> tmp(map.shape());
75 nda::copy(map, tmp);
76 const cTType<Scalar, Rank> out(std::move(tmp));
77 return out;
78 }
79
80 // map constructors
81 template <typename Scalar, std::size_t Rank>
82 static cMapTType<Scalar, Rank> cMap(const Scalar* data, const std::array<Indextype, Rank>& dims)
83 {
84 return cMapTType<Scalar, Rank>(data, as_tuple(dims));
85 }
86
87 template <typename Scalar, std::size_t Rank>
88 static MapTType<Scalar, Rank> Map(Scalar* data, const std::array<Indextype, Rank>& dims)
89 {
90 return MapTType<Scalar, Rank>(data, as_tuple(dims));
91 }
92
93 // initialization
94 template <typename Scalar, std::size_t Rank>
96 {
97 T.for_each_value([](Scalar& d) { d = 0.; });
98 }
99
100 template <typename Scalar, std::size_t Rank>
102 {
103 T.for_each_value([](Scalar& d) { d = random::threadSafeRandUniform<Scalar, Scalar>(-1., 1.); });
104 }
105
106 template <typename Scalar, std::size_t Rank>
107 static void setConstant(TType<Scalar, Rank>& T, const Scalar& val)
108 {
109 T.for_each_value([val](Scalar& d) { d = val; });
110 }
111
112 template <typename Scalar, int Rank>
113 static void setVal(TType<Scalar, Rank>& T, const std::array<Indextype, Rank>& index, const Scalar& val)
114 {
115 T(as_tuple(index)) = val;
116 }
117
118 template <typename Scalar, int Rank>
119 static Scalar getVal(const TType<Scalar, Rank>& T, const std::array<Indextype, Rank>& index)
120 {
121 if constexpr(Rank == 0) {
122 return T();
123 } else {
124 return T(as_tuple(index));
125 }
126 }
127
128 // raw data
129 template <typename Scalar, int Rank>
130 static const Scalar* get_raw_data(const TType<Scalar, Rank>& T)
131 {
132 return T.data();
133 }
134
135 template <typename Scalar, int Rank>
137 {
138 return T.data();
139 }
140
141 // shape info
142 template <typename Scalar, std::size_t Rank>
143 static std::array<Indextype, Rank> dimensions(const TType<Scalar, Rank>& T)
144 {
145 std::array<Indextype, Rank> out;
146 auto tmp = nda::internal::tuple_to_array<nda::dim<>>(T.shape().dims());
147 for(std::size_t d = 0; d < Rank; d++) { out[d] = tmp[d].extent(); }
148 return out;
149 }
150
151 // tensorProd
152 template <typename Scalar, std::size_t Rank>
154 {
155 std::array<Indextype, 2 * Rank> tmp_dims;
156 std::array<Indextype, Rank> out_dims;
157 auto dim1 = dimensions<Scalar, Rank>(T1);
158 auto dim2 = dimensions<Scalar, Rank>(T2);
159 for(std::size_t i = 0; i < Rank; i++) {
160 tmp_dims[i] = dim2[i];
161 tmp_dims[i + Rank] = dim1[i];
162 out_dims[i] = dim1[i] * dim2[i];
163 }
164 TType<Scalar, 2 * Rank> tmp(as_tuple(tmp_dims));
165
166 tmp = contract<Scalar, Rank, Rank>(T2, T1);
167
168 TType<Scalar, Rank> res(as_tuple(out_dims));
169
170 if constexpr(Rank == 1) {
171 res = reshape<Scalar, 2 * Rank, Rank>(shuffle<Scalar, 2 * Rank>(tmp, seq::make<Indextype, 2>{}), out_dims);
172 } else {
173 seq::zip<seq::make<Indextype, Rank>, seq::make<Indextype, Rank, Rank>> shuffle_dims{};
174 res = reshape<Scalar, 2 * Rank, Rank>(shuffle<Scalar, 2 * Rank>(tmp, shuffle_dims), out_dims);
175 }
176 return res;
177
178 // cMapTType<Scalar, Rank> T2m(T2.data(), T2.shape());
179 // typedef TType<Scalar, Rank> TensorType;
180 // typedef Indextype Index;
181 // std::array<Index, Rank> dims;
182 // std::array<Index, Rank> dim1_array;
183 // std::size_t tmp = 0;
184 // for(const auto& d : nda::internal::tuple_to_array<nda::dim<>>(T1.shape().dims())) {
185 // dim1_array[tmp] = d.extent();
186 // tmp++;
187 // }
188 // std::array<Index, Rank> dim2_array;
189 // tmp = 0;
190 // for(const auto& d : nda::internal::tuple_to_array<nda::dim<>>(T2.shape().dims())) {
191 // dim2_array[tmp] = d.extent();
192 // tmp++;
193 // }
194
195 // for(Index i = 0; i < T1.rank(); i++) { dims[i] = dim1_array[i] * dim2_array[i]; }
196
197 // TensorType res(as_tuple(dims));
198 // res.for_each_value([](Scalar& d) { d = 0.; });
199 // std::array<Index, Rank> extents = dim2_array;
200
201 // std::vector<std::size_t> vec_dims;
202 // for(const auto& d : dim1_array) { vec_dims.push_back(d); }
203 // NestedLoopIterator Nelly(T1.rank(), vec_dims);
204
205 // for(std::size_t i = Nelly.begin(); i != Nelly.end(); i++) {
206 // std::array<Index, Rank> indices;
207 // for(Index j = 0; j < T1.rank(); j++) { indices[j] = Nelly(j); }
208 // std::array<Index, Rank> offsets;
209 // for(Index i = 0; i < T1.rank(); i++) { offsets[i] = indices[i] * dim2_array[i]; }
210
211 // std::array<nda::interval<>, Rank> slices;
212 // for(std::size_t r = 0; r < Rank; r++) { slices[r] = nda::interval<>(offsets[r], extents[r]); }
213 // nda::dense_shape<Rank> new_s(as_tuple(slices));
214 // new_s.resolve();
215 // T2m.set_shape(new_s);
216 // nda::copy(T2m, res(as_tuple(slices)));
217 // res(as_tuple(slices)).for_each_value([&T1, &indices](Scalar& val) { val = val * T1(as_tuple(indices)); });
218 // ++Nelly;
219 // }
220 // return res;
221 }
222
223 template <typename Scalar, std::size_t Rank, Indextype... Is, typename Expr1, typename Expr2>
224 static void addScale_helper(const Expr1& src, Expr2& dst, const Scalar& scale, seq::iseq<Indextype, Is...> S)
225 {
226 nda::ein_reduce(nda::ein<Is...>(dst) += nda::ein<>(scale) * nda::ein<Is...>(src));
227 }
228
229 template <typename Scalar, std::size_t Rank, typename Expr1, typename Expr2>
230 static void addScale(const Expr1& src, Expr2& dst, const Scalar& scale)
231 {
232 return addScale_helper<Scalar, Rank>(src, dst, scale, seq::make<Indextype, Rank>());
233 }
234
235 // methods rvalue
236 template <typename Scalar, std::size_t Rank1, std::size_t Rank2, Indextype... Is1, Indextype... Is2, Indextype... Ist>
238 const TType<Scalar, Rank2>& T2,
239 seq::iseq<Indextype, Is1...> S1,
240 seq::iseq<Indextype, Is2...> S2,
241 seq::iseq<Indextype, Ist...> St)
242 {
243 return nda::make_ein_sum<Scalar, Ist...>(nda::ein<Is1...>(T1) * nda::ein<Is2...>(T2));
244 }
245
246 template <typename Scalar, std::size_t Rank1, std::size_t Rank2, Indextype... Is>
247 static TType<Scalar, Rank1 + Rank2 - sizeof...(Is)> contract(const TType<Scalar, Rank1>& T1, const TType<Scalar, Rank2>& T2)
248 {
249 static_assert(sizeof...(Is) % 2 == 0);
250 constexpr Indextype Ncon = sizeof...(Is) / 2;
251 static_assert(Ncon <= 4, "Contractions of more than 4 legs is currently not implemented for ArrayTensorLib");
252 static_assert(Rank1 + Rank2 >= Ncon);
253
254 constexpr Indextype Rank1i = static_cast<Indextype>(Rank1);
255 constexpr Indextype Rank2i = static_cast<Indextype>(Rank2);
256
257 using seq1 = seq::make<Indextype, Rank1i>; // 0, 1, ..., Rank1-1
258 using seq2 = seq::make<Indextype, Rank2i, Rank1i>; // Rank1, Rank+1, ..., Rank1+Rank2-1
259 using seqC = seq::iseq<Indextype, Is...>;
260
261 if constexpr(Ncon == 0) {
262 return contract_helper<Scalar, Rank1, Rank2>(T1, T2, seq1{}, seq2{}, seq::concat<seq1, seq2>{});
263 } else {
264 using mod_seq1 = seq_replace<Indextype, seq::at<0, seqC>, 100, seq1>;
265 using mod_seq2 = seq_replace<Indextype, seq::at<1, seqC> + Rank1i, 100, seq2>;
266 using rem_seq1 = seq::remove<seq::at<0, seqC>, seq1>;
267 using rem_seq2 = seq::remove<seq::at<1, seqC> + Rank1i, seq2>;
268 if constexpr(Ncon == 1) {
269 return contract_helper<Scalar, Rank1, Rank2>(T1, T2, mod_seq1{}, mod_seq2{}, seq::concat<rem_seq1, rem_seq2>{});
270 } else {
271 using mod_seq11 = seq_replace<Indextype, seq::at<2, seqC>, 101, mod_seq1>;
272 using mod_seq22 = seq_replace<Indextype, seq::at<3, seqC> + Rank1i, 101, mod_seq2>;
273 using rem_seq11 = seq::remove<seq::at<2, seqC>, rem_seq1>;
274 using rem_seq22 = seq::remove<seq::at<3, seqC> + Rank1i, rem_seq2>;
275 if constexpr(Ncon == 2) {
276 return contract_helper<Scalar, Rank1, Rank2>(T1, T2, mod_seq11{}, mod_seq22{}, seq::concat<rem_seq11, rem_seq22>{});
277 } else {
278 using mod_seq111 = seq_replace<Indextype, seq::at<4, seqC>, 102, mod_seq11>;
279 using mod_seq222 = seq_replace<Indextype, seq::at<5, seqC> + Rank1i, 102, mod_seq22>;
280 using rem_seq111 = seq::remove<seq::at<4, seqC>, rem_seq11>;
281 using rem_seq222 = seq::remove<seq::at<5, seqC> + Rank1i, rem_seq22>;
282 if constexpr(Ncon == 3) {
283 return contract_helper<Scalar, Rank1, Rank2>(T1, T2, mod_seq111{}, mod_seq222{}, seq::concat<rem_seq111, rem_seq222>{});
284 } else {
285 using mod_seq1111 = seq_replace<Indextype, seq::at<6, seqC>, 103, mod_seq111>;
286 using mod_seq2222 = seq_replace<Indextype, seq::at<7, seqC> + Rank1i, 103, mod_seq222>;
287 using rem_seq1111 = seq::remove<seq::at<6, seqC>, rem_seq111>;
288 using rem_seq2222 = seq::remove<seq::at<7, seqC> + Rank1i, rem_seq222>;
289 if constexpr(Ncon == 4) {
290 return contract_helper<Scalar, Rank1, Rank2>(
291 T1, T2, mod_seq1111{}, mod_seq2222{}, seq::concat<rem_seq1111, rem_seq2222>{});
292 }
293 }
294 }
295 }
296 }
297 }
298
299 template <typename Expr, Indextype... p>
300 static auto shuffle_view(const Expr& T)
301 {
302 // static_assert(Rank == sizeof...(p));
303 return nda::transpose<p...>(T);
304 }
305
306 template <typename Scalar, std::size_t Rank, Indextype... p>
308 {
309 static_assert(Rank == sizeof...(p));
310 std::array<Indextype, Rank> perm = {p...};
311 std::array<Indextype, Rank> dims;
312 for(std::size_t r = 0; r < Rank; r++) { dims[r] = T.shape().dim(perm[r]).extent(); }
313
314 nda::dense_shape<Rank> shp(as_tuple(dims));
315 return make_copy(nda::transpose<p...>(T), shp);
316 }
317
318 template <typename Scalar, std::size_t Rank, Indextype... p>
320 {
321 static_assert(Rank == sizeof...(p));
322 std::array<Indextype, Rank> perm = {p...};
323 std::array<Indextype, Rank> dims;
324 for(std::size_t r = 0; r < Rank; r++) { dims[r] = T.shape().dim(perm[r]).extent(); }
325
326 nda::dense_shape<Rank> shp(as_tuple(dims));
327 return make_copy(nda::transpose<p...>(T), shp);
328 }
329
330 template <typename Scalar, std::size_t Rank, Indextype... p>
331 static TType<Scalar, Rank> shuffle(const TType<Scalar, Rank>& T, seq::iseq<Indextype, p...> s)
332 {
333 static_assert(Rank == sizeof...(p));
334 std::array<Indextype, Rank> perm = {p...};
335 std::array<Indextype, Rank> dims;
336 for(std::size_t r = 0; r < Rank; r++) { dims[r] = T.shape().dim(perm[r]).extent(); }
337
338 nda::dense_shape<Rank> shp(as_tuple(dims));
339 return make_copy(nda::transpose<p...>(T), shp);
340 }
341
342 template <typename Scalar, std::size_t Rank, Indextype... p>
343 static auto shuffle_view(const cMapTType<Scalar, Rank>& T, seq::iseq<Indextype, p...> s)
344 {
345 static_assert(Rank == sizeof...(p));
346 return nda::transpose<p...>(T);
347 }
348
349 template <typename Scalar, std::size_t Rank1, std::size_t Rank2>
350 static TType<Scalar, Rank2> reshape(const TType<Scalar, Rank1>& T, const std::array<Indextype, Rank2>& dims)
351 {
352 cMapTType<Scalar, Rank2> map(T.data(), as_tuple(dims));
353 return construct<Scalar, Rank2>(map);
354 }
355
356 // methods lvalue
357 template <typename Scalar, std::size_t Rank1, std::size_t Rank2>
358 static auto slice(TType<Scalar, Rank1>& T, const std::array<Indextype, Rank2>& offsets, const std::array<Indextype, Rank2>& extents)
359 {
360 std::array<nda::interval<>, Rank1> slices;
361 for(std::size_t r = 0; r < Rank1; r++) { slices[r] = nda::interval<>(offsets[r], extents[r]); }
362 return T(as_tuple(slices));
363 }
364
365 template <typename Scalar, std::size_t Rank1, std::size_t Rank2>
367 const std::array<Indextype, Rank2>& offsets,
368 const std::array<Indextype, Rank2>& extents,
369 const TType<Scalar, Rank1>& S)
370 {
372 std::array<nda::interval<>, Rank1> slices;
373 for(std::size_t r = 0; r < Rank1; r++) { slices[r] = nda::interval<>(offsets[r], extents[r]); }
374 nda::dense_shape<Rank1> new_s(as_tuple(slices));
375 new_s.resolve();
376 Sm.set_shape(new_s);
377 nda::copy(Sm, T(as_tuple(slices)));
378 // return T(as_tuple(slices));
379 }
380
381 template <typename Scalar, std::size_t Rank1, std::size_t Rank2>
382 static auto reshape(TType<Scalar, Rank1>& T, const std::array<Indextype, Rank2>& dims)
383 {
384 MapTType<Scalar, Rank2> map(T.data(), as_tuple(dims));
385 return map;
386 }
387
388 template <typename Scalar, int Rank>
389 static std::string print(const TType<Scalar, Rank>& T)
390 {
391 std::stringstream ss;
392 ss << "Tensor";
393 return ss.str();
394 }
395};
396
397} // namespace Xped
398
399#endif
@ T
Definition: functions.hpp:35
XpedWorld & getUniverse()
Definition: Mpi.hpp:49
void print(seq::iseq< T, Nums... > seq)
Definition: TensorInterface_Array_impl.hpp:15
Definition: bench.cpp:62
seq::insert< seq::index_of< oldVal, S >, newVal, seq::remove< oldVal, S > > seq_replace
Definition: TensorInterface_Array_impl.hpp:26
int Indextype
Definition: PlainInterface_Cyclops_impl.cpp:10
Definition: TensorInterface_Array_impl.hpp:29
static std::array< Indextype, Rank > dimensions(const TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:143
static auto shuffle_view(const Expr &T)
Definition: TensorInterface_Array_impl.hpp:300
nda::dense_array< Scalar, Rank > TType
Definition: TensorInterface_Array_impl.hpp:44
static Scalar * get_raw_data(TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:136
const nda::dense_array< Scalar, Rank > cTType
Definition: TensorInterface_Array_impl.hpp:46
static void addScale_helper(const Expr1 &src, Expr2 &dst, const Scalar &scale, seq::iseq< Indextype, Is... > S)
Definition: TensorInterface_Array_impl.hpp:224
static cTType< Scalar, Rank > construct(const cMapTType< Scalar, Rank > &map)
Definition: TensorInterface_Array_impl.hpp:72
static auto contract_helper(const TType< Scalar, Rank1 > &T1, const TType< Scalar, Rank2 > &T2, seq::iseq< Indextype, Is1... > S1, seq::iseq< Indextype, Is2... > S2, seq::iseq< Indextype, Ist... > St)
Definition: TensorInterface_Array_impl.hpp:237
static TType< Scalar, Rank > construct(const MapTType< Scalar, Rank > &map)
Definition: TensorInterface_Array_impl.hpp:64
static nda::internal::tuple_of_n< element_t, N > as_tuple(std::array< element_t, N > const &arr, std::index_sequence< Is... >)
Definition: TensorInterface_Array_impl.hpp:31
static void setZero(TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:95
static TType< Scalar, Rank > shuffle(const TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:307
nda::index_t Indextype
Definition: TensorInterface_Array_impl.hpp:54
static TType< Scalar, Rank > shuffle(const TType< Scalar, Rank > &T, seq::iseq< Indextype, p... > s)
Definition: TensorInterface_Array_impl.hpp:331
static auto reshape(TType< Scalar, Rank1 > &T, const std::array< Indextype, Rank2 > &dims)
Definition: TensorInterface_Array_impl.hpp:382
static nda::internal::tuple_of_n< element_t, N > as_tuple(std::array< element_t, N > const &arr)
Definition: TensorInterface_Array_impl.hpp:37
static auto slice(TType< Scalar, Rank1 > &T, const std::array< Indextype, Rank2 > &offsets, const std::array< Indextype, Rank2 > &extents)
Definition: TensorInterface_Array_impl.hpp:358
static void setConstant(TType< Scalar, Rank > &T, const Scalar &val)
Definition: TensorInterface_Array_impl.hpp:107
nda::dense_array_ref< Scalar, Rank > MapTType
Definition: TensorInterface_Array_impl.hpp:49
static MapTType< Scalar, Rank > Map(Scalar *data, const std::array< Indextype, Rank > &dims)
Definition: TensorInterface_Array_impl.hpp:88
static std::string print(const TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:389
static Scalar getVal(const TType< Scalar, Rank > &T, const std::array< Indextype, Rank > &index)
Definition: TensorInterface_Array_impl.hpp:119
static TType< Scalar, Rank > construct(const std::array< Indextype, Rank > &dims, mpi::XpedWorld &world=mpi::getUniverse())
Definition: TensorInterface_Array_impl.hpp:58
static auto shuffle_view(const cMapTType< Scalar, Rank > &T, seq::iseq< Indextype, p... > s)
Definition: TensorInterface_Array_impl.hpp:343
static void setVal(TType< Scalar, Rank > &T, const std::array< Indextype, Rank > &index, const Scalar &val)
Definition: TensorInterface_Array_impl.hpp:113
static void addScale(const Expr1 &src, Expr2 &dst, const Scalar &scale)
Definition: TensorInterface_Array_impl.hpp:230
static const Scalar * get_raw_data(const TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:130
static void setRandom(TType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:101
static TType< Scalar, Rank > shuffle(const cMapTType< Scalar, Rank > &T)
Definition: TensorInterface_Array_impl.hpp:319
static TType< Scalar, Rank > tensorProd(const TType< Scalar, Rank > &T1, const TType< Scalar, Rank > &T2)
Definition: TensorInterface_Array_impl.hpp:153
static TType< Scalar, Rank1+Rank2 - sizeof...(Is)> contract(const TType< Scalar, Rank1 > &T1, const TType< Scalar, Rank2 > &T2)
Definition: TensorInterface_Array_impl.hpp:247
static cMapTType< Scalar, Rank > cMap(const Scalar *data, const std::array< Indextype, Rank > &dims)
Definition: TensorInterface_Array_impl.hpp:82
static TType< Scalar, Rank2 > reshape(const TType< Scalar, Rank1 > &T, const std::array< Indextype, Rank2 > &dims)
Definition: TensorInterface_Array_impl.hpp:350
nda::const_dense_array_ref< Scalar, Rank > cMapTType
Definition: TensorInterface_Array_impl.hpp:51
static void setSubTensor(TType< Scalar, Rank1 > &T, const std::array< Indextype, Rank2 > &offsets, const std::array< Indextype, Rank2 > &extents, const TType< Scalar, Rank1 > &S)
Definition: TensorInterface_Array_impl.hpp:366
Definition: Mpi.hpp:34