29 #ifndef _TENSOR_IMPL_HPP_
30 #define _TENSOR_IMPL_HPP_
69 template <
template <
typename>
class Matrix,
typename C>
78 template <
template <
typename>
class Matrix,
typename C>
87 template <
template <
typename>
class Matrix,
typename C>
89 : Mat(comm), upper_rank(0), axes_map(){};
97 template <
template <
typename>
class Matrix,
typename C>
109 template <
template <
typename>
class Matrix,
typename C>
111 const size_t upper_rank)
122 template <
template <
typename>
class Matrix,
typename C>
127 const size_t n = Mat.local_size();
130 for (
size_t i = 0; i < n; ++i) {
142 template <
template <
typename>
class Matrix,
typename C>
145 init(
Shape(v.size()), 0);
146 const size_t n = Mat.local_size();
148 for (
size_t i = 0; i < n; ++i) {
149 idx = global_index(i);
157 template <
template <
typename>
class Matrix,
typename C>
163 template <
template <
typename>
class Matrix,
typename C>
172 template <
template <
typename>
class Matrix,
typename C>
178 template <
template <
typename>
class Matrix,
typename C>
184 template <
template <
typename>
class Matrix,
typename C>
196 template <
template <
typename>
class Matrix,
typename C>
202 template <
template <
typename>
class Matrix,
typename C>
208 template <
template <
typename>
class Matrix,
typename C>
214 template <
template <
typename>
class Matrix,
typename C>
221 template <
template <
typename>
class Matrix,
typename C>
227 template <
template <
typename>
class Matrix,
typename C>
236 template <
template <
typename>
class Matrix,
typename C>
238 return Mat[local_idx];
245 template <
template <
typename>
class Matrix,
typename C>
247 return Mat[local_idx];
251 template <
template <
typename>
class Matrix,
typename C>
257 template <
template <
typename>
class Matrix,
typename C>
263 template <
template <
typename>
class Matrix,
typename C>
265 const size_t rank = Dim.size();
266 const size_t rank0 = upper_rank;
267 const size_t rank1 = rank - rank0;
268 const size_t l_row = Mat.local_row_size();
269 const size_t l_col = Mat.local_col_size();
270 const size_t *axes_map0 = &(axes_map[0]);
271 const size_t *axes_map1 = &(axes_map[rank0]);
273 l2g_map_row.resize(l_row * rank0);
274 l2g_map_col.resize(l_col * rank1);
276 #pragma omp parallel default(shared)
281 for (
size_t i = 0; i < rank0; ++i) dim0[i] =
int(Dim[axes_map0[i]]);
282 for (
size_t i = 0; i < rank1; ++i) dim1[i] =
int(Dim[axes_map1[i]]);
285 std::div_t divresult;
288 for (
size_t k = 0; k < l_row; ++k) {
289 map = &(l2g_map_row[k * rank0]);
290 g_row = int(Mat.global_row_index(k));
291 for (
size_t i = 0; i < rank0; ++i) {
292 divresult = std::div(g_row, dim0[i]);
293 map[i] = divresult.rem;
294 g_row = divresult.quot;
298 for (
size_t k = 0; k < l_col; ++k) {
299 map = &(l2g_map_col[k * rank1]);
300 g_col = int(Mat.global_col_index(k));
301 for (
size_t i = 0; i < rank1; ++i) {
302 divresult = std::div(g_col, dim1[i]);
303 map[i] = divresult.rem;
304 g_col = divresult.quot;
319 template <
template <
typename>
class Matrix,
typename C>
321 size_t gindex[])
const {
322 const size_t rank = Dim.size();
323 const size_t rank0 = upper_rank;
324 const size_t rank1 = rank - rank0;
325 const size_t lindex_row = Mat.local_row_index(lindex);
326 const size_t lindex_col = Mat.local_col_index(lindex);
327 const size_t *map_row = &(l2g_map_row[lindex_row * rank0]);
328 const size_t *map_col = &(l2g_map_col[lindex_col * rank1]);
329 const size_t *axes_map0 = &(axes_map[0]);
330 const size_t *axes_map1 = &(axes_map[rank0]);
331 for (
size_t i = 0; i < rank0; ++i) {
332 gindex[axes_map0[i]] = map_row[i];
334 for (
size_t i = 0; i < rank1; ++i) {
335 gindex[axes_map1[i]] = map_col[i];
352 template <
template <
typename>
class Matrix,
typename C>
354 size_t lindex,
const size_t axes_trans[],
size_t index_new[])
const {
355 const size_t rank = Dim.size();
356 const size_t rank0 = upper_rank;
357 const size_t rank1 = rank - rank0;
358 const size_t lindex_row = Mat.local_row_index(lindex);
359 const size_t lindex_col = Mat.local_col_index(lindex);
360 const size_t *map_row = &(l2g_map_row[lindex_row * rank0]);
361 const size_t *map_col = &(l2g_map_col[lindex_col * rank1]);
364 for (
size_t i = 0; i < rank0; ++i) {
365 index_new[axes_trans[i]] = map_row[i];
368 for (
size_t i = 0; i < rank1; ++i) {
369 index_new[axes_trans[i + rank0]] = map_col[i];
375 template <
template <
typename>
class Matrix,
typename C>
378 size_t &local_idx)
const {
389 template <
template <
typename>
class Matrix,
typename C>
400 template <
template <
typename>
class Matrix,
typename C>
401 void Tensor<Matrix, C>::init(
const Shape &
shape,
size_t urank,
405 const size_t rank = Dim.size();
406 assert(urank <= rank);
411 for (
size_t i = 0; i < upper_rank; ++i) n_row *=
shape[map[i]];
412 for (
size_t i = upper_rank; i < rank; ++i) n_col *=
shape[map[i]];
413 Mat.init(n_row, n_col);
423 template <
template <
typename>
class Matrix,
typename C>
425 const std::string &tag)
const {
426 if (tag.size() > 0) {
429 out <<
"Tensor: shape= " << Dim <<
" upper_rank= " << upper_rank
430 <<
" axes_map= " << axes_map <<
"\t";
441 template <
template <
typename>
class Matrix,
typename C>
443 const std::string &tag)
const {
444 const int mpisize = get_comm_size();
445 const int mpirank = get_comm_rank();
448 for (
int i = 0; i < mpisize; ++i) {
450 if (tag.size() > 0) {
453 out <<
"mpirank: " << mpirank <<
"\t";
469 template <
template <
typename>
class Matrix,
typename C>
471 const size_t rank = gindex.
size();
472 assert(rank == Dim.size());
474 size_t g_row(0), g_col(0);
475 size_t d_row(1), d_col(1);
476 for (
size_t i = 0; i < upper_rank; ++i) {
477 size_t j = axes_map[i];
478 g_row += gindex[j] * d_row;
481 for (
size_t i = upper_rank; i < rank; ++i) {
482 size_t j = axes_map[i];
483 g_col += gindex[j] * d_col;
486 return Mat.local_index(g_row, g_col, lindex);
494 template <
template <
typename>
class Matrix,
typename C>
496 const size_t rank = Dim.size();
499 Mat.global_index(lindex, g_row, g_col);
501 std::div_t divresult;
502 for (
size_t i = 0; i < upper_rank; ++i) {
503 size_t j = axes_map[i];
504 divresult = std::div(
int(g_row),
int(Dim[j]));
505 gindex[j] = divresult.rem;
506 g_row = divresult.quot;
508 for (
size_t i = upper_rank; i < rank; ++i) {
509 size_t j = axes_map[i];
510 divresult = std::div(
int(g_col),
int(Dim[j]));
511 gindex[j] = divresult.rem;
512 g_col = divresult.quot;
524 template <
template <
typename>
class Matrix,
typename C>
526 const size_t rank = Dim.size();
529 std::div_t divresult;
530 for (
size_t i = 0; i < upper_rank; ++i) {
531 size_t j = axes_map[i];
532 divresult = std::div(
int(g_row),
int(Dim[j]));
533 gindex[j] = divresult.rem;
534 g_row = divresult.quot;
536 for (
size_t i = upper_rank; i < rank; ++i) {
537 size_t j = axes_map[i];
538 divresult = std::div(
int(g_col),
int(Dim[j]));
539 gindex[j] = divresult.rem;
540 g_col = divresult.quot;
551 template <
template <
typename>
class Matrix,
typename C>
554 if (local_index(idx, li)) {
569 template <
template <
typename>
class Matrix,
typename C>
572 if (local_index(idx, li)) {
583 template <
template <
typename>
class Matrix,
typename C>
585 size_t &local_idx)
const {
586 const size_t rank = Dim.size();
587 size_t g_row(0), g_col(0);
588 size_t d_row(1), d_col(1);
589 for (
size_t i = 0; i < upper_rank; ++i) {
590 size_t j = axes_map[i];
591 g_row += index[j] * d_row;
594 for (
size_t i = upper_rank; i < rank; ++i) {
595 size_t j = axes_map[i];
596 g_col += index[j] * d_col;
599 Mat.local_position(g_row, g_col, comm_rank, local_idx);
610 template <
template <
typename>
class Matrix,
typename C>
612 const Axes &new_axes_map) {
613 if ((upper_rank == new_upper_rank) && (axes_map == new_axes_map))
return;
617 const size_t rank = this->rank();
622 for (
size_t i = 0; i < rank; ++i) {
623 dim[i] = Dim[new_axes_map[i]];
624 axes[new_axes_map[i]] = i;
626 init(dim, new_upper_rank);
630 const size_t local_size = T_old.local_size();
631 std::vector<int> dest_mpirank(local_size);
632 std::vector<unsigned long int> local_position(local_size);
634 T_old.prep_local_to_global();
635 this->prep_global_to_local();
637 #pragma omp parallel default(shared)
643 for (
size_t i = 0; i < local_size; ++i) {
644 T_old.global_index_fast(i, index);
648 this->local_position(index, dest, pos);
650 local_position[i] = pos;
651 dest_mpirank[i] = dest;
666 template <
template <
typename>
class Matrix,
typename C>
668 const size_t rank = Dim.size();
672 Axes map_now = axes_map;
675 for (
size_t i = 0; i < rank; ++i) {
676 axes_inv[axes[i]] = i;
679 for (
size_t i = 0; i < rank; ++i) {
680 Dim[i] = dim_now[axes[i]];
681 axes_map[i] = axes_inv[map_now[i]];
698 template <
template <
typename>
class Matrix,
typename C>
699 template <
typename D>
702 assert(Dim[n_axes] <= vec.size());
703 const size_t local_size = this->local_size();
704 prep_local_to_global();
705 #pragma omp parallel default(shared)
710 for (
size_t i = 0; i < local_size; ++i) {
711 global_index_fast(i, idx);
712 Mat[i] *= vec[idx[n_axes]];
731 template <
template <
typename>
class Matrix,
typename C>
732 template <
typename D0,
typename D1>
734 const std::vector<D0> &vec0,
size_t n_axes0,
const std::vector<D1> &vec1,
736 assert(Dim[n_axes0] <= vec0.size());
737 assert(Dim[n_axes1] <= vec1.size());
738 const size_t local_size = this->local_size();
739 prep_local_to_global();
740 #pragma omp parallel default(shared)
745 for (
size_t i = 0; i < local_size; ++i) {
746 global_index_fast(i, idx);
747 Mat[i] *= vec0[idx[n_axes0]] * vec1[idx[n_axes1]];
768 template <
template <
typename>
class Matrix,
typename C>
769 template <
typename D0,
typename D1,
typename D2>
771 const std::vector<D0> &vec0,
size_t n_axes0,
const std::vector<D1> &vec1,
772 size_t n_axes1,
const std::vector<D2> &vec2,
size_t n_axes2) {
773 assert(Dim[n_axes0] <= vec0.size());
774 assert(Dim[n_axes1] <= vec1.size());
775 assert(Dim[n_axes2] <= vec2.size());
776 const size_t local_size = this->local_size();
777 prep_local_to_global();
778 #pragma omp parallel default(shared)
783 for (
size_t i = 0; i < local_size; ++i) {
784 global_index_fast(i, idx);
785 Mat[i] *= vec0[idx[n_axes0]] * vec1[idx[n_axes1]] * vec2[idx[n_axes2]];
808 template <
template <
typename>
class Matrix,
typename C>
809 template <
typename D0,
typename D1,
typename D2,
typename D3>
811 const std::vector<D0> &vec0,
size_t n_axes0,
const std::vector<D1> &vec1,
812 size_t n_axes1,
const std::vector<D2> &vec2,
size_t n_axes2,
813 const std::vector<D3> &vec3,
size_t n_axes3) {
814 assert(Dim[n_axes0] <= vec0.size());
815 assert(Dim[n_axes1] <= vec1.size());
816 assert(Dim[n_axes2] <= vec2.size());
817 assert(Dim[n_axes3] <= vec3.size());
818 const size_t local_size = this->local_size();
819 prep_local_to_global();
820 #pragma omp parallel default(shared)
825 for (
size_t i = 0; i < local_size; ++i) {
826 global_index_fast(i, idx);
827 Mat[i] *= vec0[idx[n_axes0]] * vec1[idx[n_axes1]] * vec2[idx[n_axes2]] *
845 template <
template <
typename>
class Matrix,
typename C>
848 const size_t i_begin,
849 const size_t i_end) {
850 assert(rank() == a.
rank());
851 assert(n_axes < rank());
852 assert(i_begin < i_end);
853 assert(i_end <=
shape()[n_axes]);
854 assert(i_end - i_begin == a.
shape()[n_axes]);
858 std::vector<int> dest_mpirank(local_size);
859 std::vector<unsigned long int> local_position(local_size);
862 prep_global_to_local();
864 #pragma omp parallel default(shared)
869 for (
size_t i = 0; i < local_size; ++i) {
871 index[n_axes] += i_begin;
875 this->local_position(index, dest, pos);
877 local_position[i] = pos;
878 dest_mpirank[i] = dest;
900 template <
template <
typename>
class Matrix,
typename C>
902 const Index &index_begin,
903 const Index &index_end) {
904 const size_t nr = rank();
905 assert(nr == a.
rank());
906 assert(index_begin.
size() == nr);
907 assert(index_end.
size() == nr);
908 for (
size_t r = 0; r < nr; ++r) {
909 assert(index_end[r] <=
shape()[r]);
910 assert(index_begin[r] <= index_end[r]);
915 std::vector<int> dest_mpirank(local_size);
916 std::vector<unsigned long int> local_position(local_size);
919 prep_global_to_local();
921 #pragma omp parallel default(shared)
926 for (
size_t i = 0; i < local_size; ++i) {
928 for (
size_t r = 0; r < nr; ++r) {
929 if (index_begin[r] != index_end[r]) index[r] += index_begin[r];
934 this->local_position(index, dest, pos);
936 local_position[i] = pos;
937 dest_mpirank[i] = dest;
954 template <
template <
typename>
class Matrix,
typename C>
956 const size_t n = rank();
957 if (!(axes_map ==
range(n))) {
958 change_configuration(n / 2,
range(n));
970 template <
template <
typename>
class Matrix,
typename C>
972 const size_t n = rank();
973 if (!(axes_map ==
range(n))) {
974 change_configuration(n / 2,
range(n));
976 return get_matrix().flatten();
980 template <
template <
typename>
class Matrix,
typename C>
982 assert(Dim == rhs.
shape());
989 template <
template <
typename>
class Matrix,
typename C>
991 assert(Dim == rhs.
shape());
998 template <
template <
typename>
class Matrix,
typename C>
1005 template <
template <
typename>
class Matrix,
typename C>
1012 template <
template <
typename>
class Matrix,
typename C>
1015 for (
int i = 0; i < n; ++i) Mat[i] = rhs;
1024 template <
template <
typename>
class Matrix,
typename C>
1025 template <
typename UnaryOperation>
1040 template <
template <
typename>
class Matrix,
typename C>
1055 template <
template <
typename>
class Matrix,
typename C>
1058 const size_t rank = T.
rank();
1060 assert(urank_new <= rank);
1070 for (
size_t r = 0; r < rank; ++r) {
1071 dim_new[r] = dim_old[axes[r]];
1079 std::vector<int> dest_mpirank(local_size);
1080 std::vector<unsigned long int> local_position(local_size);
1085 #pragma omp parallel default(shared)
1088 size_t d_offset[rank];
1089 size_t d_row(1), d_col(1);
1090 for (
size_t r = 0; r < urank_new; ++r) {
1091 d_offset[r] = d_row;
1092 d_row *= dim_new[r];
1094 for (
size_t r = urank_new; r < rank; ++r) {
1095 d_offset[r] = d_col;
1096 d_col *= dim_new[r];
1100 size_t axes_inv[rank];
1101 size_t axes_trans[rank];
1102 for (
size_t r = 0; r < rank; ++r) {
1103 axes_inv[axes[r]] = r;
1105 for (
size_t r = 0; r < rank; ++r) {
1106 axes_trans[r] = axes_inv[axes_map[r]];
1109 size_t index_new[rank];
1112 for (
size_t i = 0; i < local_size; ++i) {
1117 for (
size_t r = 0; r < urank_new; ++r) {
1118 g_row += index_new[r] * d_offset[r];
1120 for (
size_t r = urank_new; r < rank; ++r) {
1121 g_col += index_new[r] * d_offset[r];
1148 template <
template <
typename>
class Matrix,
typename C>
1153 const size_t rank =
shape.size();
1154 const size_t rank_new = shape_new.
size();
1161 std::vector<int> dest_mpirank(local_size);
1162 std::vector<unsigned long int> local_position(local_size);
1167 #pragma omp parallel default(shared)
1169 Index index, index_new;
1171 index_new.
resize(rank_new);
1173 for (
size_t i = 0; i < local_size; ++i) {
1175 size_t global_position(0);
1177 for (
size_t r = 0; r < rank; ++r) {
1178 global_position += index[r] * dim;
1182 for (
size_t r = 0; r < rank_new; ++r) {
1183 index_new[r] = global_position % shape_new[r];
1184 global_position /= shape_new[r];
1191 local_position[i] = pos;
1192 dest_mpirank[i] = dest;
1214 template <
template <
typename>
class Matrix,
typename C>
1216 size_t i_begin,
size_t i_end) {
1219 assert(n_axes < T.
rank());
1220 assert(i_begin < i_end);
1221 assert(i_end <=
shape[n_axes]);
1224 shape_new[n_axes] = i_end - i_begin;
1231 std::vector<int> dest_mpirank(local_size);
1232 std::vector<unsigned long int> local_position(local_size);
1237 #pragma omp parallel default(shared)
1242 for (
size_t i = 0; i < local_size; ++i) {
1244 if (index[n_axes] >= i_begin && index[n_axes] < i_end) {
1245 index[n_axes] -= i_begin;
1251 local_position[i] = pos;
1252 dest_mpirank[i] = dest;
1255 local_position[i] = 0;
1256 dest_mpirank[i] = mpisize;
1282 template <
template <
typename>
class Matrix,
typename C>
1284 const Index &index_end) {
1287 const size_t rank = T.
rank();
1288 assert(index_begin.
size() == rank);
1289 assert(index_end.
size() == rank);
1292 for (
size_t r = 0; r < rank; ++r) {
1293 assert(index_end[r] <=
shape[r]);
1294 assert(index_begin[r] <= index_end[r]);
1295 shape_new[r] = index_end[r] - index_begin[r];
1296 if (shape_new[r] == 0) shape_new[r] =
shape[r];
1304 std::vector<int> dest_mpirank(local_size);
1305 std::vector<unsigned long int> local_position(local_size);
1310 #pragma omp parallel default(shared)
1315 for (
size_t i = 0; i < local_size; ++i) {
1318 bool is_send =
true;
1319 for (
size_t r = 0; r < rank; ++r) {
1320 size_t idx = index[r];
1321 if (index_begin[r] == index_end[r]) {
1323 }
else if (idx >= index_begin[r] && idx < index_end[r]) {
1324 index[r] -= index_begin[r];
1336 local_position[i] = pos;
1337 dest_mpirank[i] = dest;
1340 local_position[i] = 0;
1341 dest_mpirank[i] = mpisize;
1362 template <
template <
typename>
class Matrix,
typename C>
1364 assert(T.
rank() == shape_new.
size());
1372 std::vector<int> dest_mpirank(local_size);
1373 std::vector<unsigned long int> local_position(local_size);
1378 #pragma omp parallel default(shared)
1383 for (
size_t i = 0; i < local_size; ++i) {
1390 local_position[i] = pos;
1391 dest_mpirank[i] = dest;
1408 template <
template <
typename>
class Matrix,
typename C>
1410 assert(M.
rank() == 2);
1428 template <
template <
typename>
class Matrix,
typename C>
1430 assert(axes_1.
size() == axes_2.
size());
1437 const size_t l = axes_1.
size();
1443 for (
size_t i = 0; i < n; ++i) {
1446 for (
size_t k = 0; k < l; ++k) {
1447 if (index[axes_1[k]] != index[axes_2[k]]) {
1474 template <
template <
typename>
class Matrix,
typename C>
1476 const Axes &axes_a,
const Axes &axes_b) {
1482 const size_t rank = A.
rank();
1489 for (
size_t i = 0; i < rank; ++i) {
1490 axes_a_inv[axes_a[i]] = i;
1492 for (
size_t i = 0; i < rank; ++i) {
1493 axes[i] = axes_b[axes_a_inv[axes_map[i]]];
1500 for (
size_t i = 0; i < n; ++i) {
1501 sum += A[i] * B_t[i];
1518 template <
template <
typename>
class Matrix,
typename C>
1520 const Axes &axes_2) {
1522 assert(axes_1.
size() == axes_2.
size());
1524 if (axes_1.
size() == 0)
return T;
1531 Axes v = axes_1 + axes_2;
1534 size_t n = v.
size();
1535 for (
size_t i = 0; i < T.
rank(); ++i) {
1536 if (k < n && i == v[k]) {
1549 std::vector<int> dest_mpirank(T.
local_size());
1550 std::vector<unsigned long int> local_position(T.
local_size());
1552 Index index, index_new;
1556 const size_t n = axes_1.
size();
1558 for (
size_t i = 0; i < T.
local_size(); ++i) {
1561 for (
size_t k = 0; k < n; ++k) {
1562 if (index[axes_1[k]] != index[axes_2[k]]) {
1569 for (
size_t k = 0; k < index_new.
size(); ++k) {
1570 index_new[k] = index[axes_new[k]];
1577 local_position[i] = pos;
1578 dest_mpirank[i] = dest;
1581 local_position[i] = 0;
1582 dest_mpirank[i] = mpisize;
1611 template <
template <
typename>
class Matrix,
typename C>
1618 Shape shape_c = shape_a;
1619 size_t n = shape_a.
size();
1621 axes_trans.
resize(2 * n);
1622 for (
size_t i = 0; i < shape_b.
size(); ++i) {
1623 shape_c[i] *= shape_b[i];
1624 axes_trans[2 * i] = i;
1625 axes_trans[2 * i + 1] = i + n;
1647 template <
template <
typename>
class Matrix,
typename C>
1650 const Axes &axes_b) {
1651 assert(axes_a.
size() == axes_b.
size());
1655 for (
size_t i = 0; i < axes_a.
size(); ++i) {
1656 assert(shape_a[axes_a[i]] == shape_b[axes_b[i]]);
1662 const size_t rank_row_c = a.
rank() - axes_a.
size();
1663 const size_t rank_col_c = b.
rank() - axes_b.
size();
1664 shape_c.
resize(rank_row_c + rank_col_c);
1672 const size_t rank = a.
rank();
1673 const size_t rank_row = rank - axes_a.
size();
1674 const size_t rank_col = axes_a.
size();
1676 for (
size_t i = 0; i < rank; ++i) v[i] = i;
1677 for (
size_t i = 0; i < rank_col; ++i) v[axes_a[i]] = rank;
1678 std::sort(v, v + rank);
1679 for (
size_t i = 0; i < rank_col; ++i) v[rank_row + i] = axes_a[i];
1681 trans_axes_a.
assign(rank, v);
1684 for (
size_t i = 0; i < rank_row; ++i) shape_c[i] = shape_a[v[i]];
1688 const size_t rank = b.
rank();
1689 const size_t rank_row = axes_b.
size();
1690 const size_t rank_col = rank - axes_b.
size();
1692 for (
size_t i = 0; i < rank; ++i) v[i] = i;
1693 for (
size_t i = 0; i < rank_row; ++i) v[axes_b[i]] = 0;
1694 std::sort(v, v + rank);
1695 for (
size_t i = 0; i < rank_row; ++i) v[i] = axes_b[i];
1697 trans_axes_b.
assign(rank, v);
1700 for (
size_t i = 0; i < rank_col; ++i)
1701 shape_c[i + rank_row_c] = shape_b[v[i + rank_row]];
1706 transpose(b, trans_axes_b, urank_b).get_matrix(),
1721 template <
template <
typename>
class Matrix,
typename C>
1723 assert(a.
rank() == 2);
1742 template <
template <
typename>
class Matrix,
typename C>
1745 assert(a.
rank() == 2);
1762 template <
template <
typename>
class Matrix,
typename C>
1764 std::vector<double> &s) {
1765 assert(axes_row.
size() > 0);
1766 assert(axes_col.
size() > 0);
1769 const size_t rank = a.
rank();
1770 const size_t urank = axes_row.
size();
1772 Axes axes = axes_row + axes_col;
1777 size_t d_row(1), d_col(1);
1778 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
1779 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
1780 size_t size = (d_row < d_col) ? d_row : d_col;
1810 template <
template <
typename>
class Matrix,
typename C>
1813 assert(axes_row.
size() > 0);
1814 assert(axes_col.
size() > 0);
1817 const size_t rank = a.
rank();
1818 const size_t urank = axes_row.
size();
1820 Axes axes = axes_row + axes_col;
1825 size_t d_row(1), d_col(1);
1826 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
1827 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
1828 size_t size = (d_row < d_col) ? d_row : d_col;
1831 shape_u.
resize(urank + 1);
1832 for (
size_t i = 0; i < urank; ++i) shape_u[i] =
shape[i];
1833 shape_u[urank] = size;
1836 shape_vt.
resize(rank - urank + 1);
1838 for (
size_t i = urank; i < rank; ++i) shape_vt[i - urank + 1] =
shape[i];
1840 size_t urank_u = urank;
1841 size_t urank_vt = 1;
1865 template <
template <
typename>
class Matrix,
typename C>
1867 const size_t target_rank) {
1868 int info =
svd(a, s);
1869 if (s.size() > target_rank) s.resize(target_rank);
1889 template <
template <
typename>
class Matrix,
typename C>
1892 const size_t target_rank) {
1893 int info =
svd(a, u, s, vt);
1894 if (s.size() > target_rank) {
1895 s.resize(target_rank);
1896 u =
slice(u, 1, 0, target_rank);
1897 vt =
slice(vt, 0, 0, target_rank);
1916 template <
template <
typename>
class Matrix,
typename C>
1918 std::vector<double> &s,
const size_t target_rank) {
1919 int info =
svd(a, axes_row, axes_col, s);
1920 if (s.size() > target_rank) s.resize(target_rank);
1947 template <
template <
typename>
class Matrix,
typename C>
1950 const size_t target_rank) {
1951 int info =
svd(a, axes_row, axes_col, u, s, vt);
1952 if (s.size() > target_rank) {
1953 s.resize(target_rank);
1954 u =
slice(u, axes_row.
size(), 0, target_rank);
1955 vt =
slice(vt, 0, 0, target_rank);
1973 template <
template <
typename>
class Matrix,
typename C>
1975 assert(a.
rank() == 2);
2005 template <
template <
typename>
class Matrix,
typename C>
2008 assert(axes_row.
size() > 0);
2009 assert(axes_col.
size() > 0);
2012 const size_t rank = a.
rank();
2013 const size_t urank = axes_row.
size();
2016 Axes axes = axes_row + axes_col;
2019 for (
size_t i = 0; i < rank; ++i)
shape[i] = shape_a[axes[i]];
2021 size_t d_row(1), d_col(1);
2022 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
2023 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
2024 size_t size = (d_row < d_col) ? d_row : d_col;
2037 shape_q.
resize(urank + 1);
2038 for (
size_t i = 0; i < urank; ++i) shape_q[i] =
shape[i];
2039 shape_q[urank] = size;
2042 shape_r.
resize(rank - urank + 1);
2044 for (
size_t i = urank; i < rank; ++i) shape_r[i - urank + 1] =
shape[i];
2047 if (d_row > d_col) {
2050 }
else if (d_row < d_col) {
2070 template <
template <
typename>
class Matrix,
typename C>
2073 assert(a.
rank() == 2);
2079 size_t n =
shape[0];
2096 template <
template <
typename>
class Matrix,
typename C>
2098 assert(a.
rank() == 2);
2104 size_t n =
shape[0];
2134 template <
template <
typename>
class Matrix,
typename C>
2137 assert(axes_row.
size() > 0);
2138 assert(axes_col.
size() > 0);
2140 const size_t rank = a.
rank();
2141 const size_t urank = axes_row.
size();
2143 Axes axes = axes_row + axes_col;
2148 size_t d_row(1), d_col(1);
2149 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
2150 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
2151 size_t size = (d_row < d_col) ? d_row : d_col;
2153 assert(d_row == d_col);
2156 shape_z.
resize(urank + 1);
2157 for (
size_t i = 0; i < urank; ++i) shape_z[i] =
shape[i];
2158 shape_z[urank] = size;
2179 template <
template <
typename>
class Matrix,
typename C>
2181 std::vector<double> &w) {
2182 assert(axes_row.
size() > 0);
2183 assert(axes_col.
size() > 0);
2185 const size_t rank = a.
rank();
2186 const size_t urank = axes_row.
size();
2188 Axes axes = axes_row + axes_col;
2193 size_t d_row(1), d_col(1);
2194 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
2195 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
2196 size_t size = (d_row < d_col) ? d_row : d_col;
2199 assert(d_row == d_col);
2239 template <
template <
typename>
class Matrix,
typename C>
2242 const Axes &axes_row_b,
const Axes &axes_col_b, std::vector<double> &w,
2244 assert(axes_row_a.
size() > 0);
2245 assert(axes_col_a.
size() > 0);
2246 assert(axes_row_b.
size() > 0);
2247 assert(axes_col_b.
size() > 0);
2249 const size_t rank_a = a.
rank();
2250 const size_t rank_b = b.
rank();
2251 const size_t urank_a = axes_row_a.
size();
2252 const size_t urank_b = axes_row_b.
size();
2253 Axes axes_a = axes_row_a + axes_col_a;
2254 Axes axes_b = axes_row_b + axes_col_b;
2259 size_t d_row_a(1), d_col_a(1);
2260 size_t d_row_b(1), d_col_b(1);
2261 for (
size_t i = 0; i < urank_a; ++i) d_row_a *= shape_a[i];
2262 for (
size_t i = 0; i < urank_b; ++i) d_row_b *= shape_b[i];
2263 for (
size_t i = urank_a; i < rank_a; ++i) d_col_a *= shape_a[i];
2264 for (
size_t i = urank_b; i < rank_b; ++i) d_col_b *= shape_b[i];
2266 assert(d_row_a == d_col_a);
2267 assert(d_row_b == d_col_b);
2268 assert(d_row_a == d_row_b);
2269 size_t size = d_row_a;
2272 shape_z.
resize(rank_a - urank_a + 1);
2273 for (
size_t i = urank_a; i < rank_a; ++i) shape_z[i - urank_a] = shape_a[i];
2274 shape_z[rank_a - urank_a] = size;
2294 template <
template <
typename>
class Matrix,
typename C>
2297 assert(a.
rank() == 2);
2303 size_t n =
shape[0];
2324 template <
template <
typename>
class Matrix,
typename C>
2326 assert(a.
rank() == 2);
2332 size_t n =
shape[0];
2361 template <
template <
typename>
class Matrix,
typename C>
2364 assert(axes_row.
size() > 0);
2365 assert(axes_col.
size() > 0);
2367 const size_t rank = a.
rank();
2368 const size_t urank = axes_row.
size();
2370 Axes axes = axes_row + axes_col;
2375 size_t d_row(1), d_col(1);
2376 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
2377 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
2378 size_t size = (d_row < d_col) ? d_row : d_col;
2380 assert(d_row == d_col);
2383 shape_z.
resize(urank + 1);
2384 for (
size_t i = 0; i < urank; ++i) shape_z[i] =
shape[i];
2385 shape_z[urank] = size;
2410 template <
template <
typename>
class Matrix,
typename C>
2412 std::vector<complex> &w) {
2413 assert(axes_row.
size() > 0);
2414 assert(axes_col.
size() > 0);
2416 const size_t rank = a.
rank();
2417 const size_t urank = axes_row.
size();
2419 Axes axes = axes_row + axes_col;
2424 size_t d_row(1), d_col(1);
2425 for (
size_t i = 0; i < urank; ++i) d_row *=
shape[i];
2426 for (
size_t i = urank; i < rank; ++i) d_col *=
shape[i];
2427 size_t size = (d_row < d_col) ? d_row : d_col;
2430 assert(d_row == d_col);
2446 template <
template <
typename>
class Matrix,
typename C>
2448 std::vector<C> &x) {
2449 assert(a.
rank() == 2);
2470 template <
template <
typename>
class Matrix,
typename C>
2473 assert(a.
rank() == 2);
2474 assert(b.
rank() == 2 || b.
rank() == 1);
2479 if (b.
rank() == 2) {
2516 template <
template <
typename>
class Matrix,
typename C>
2519 const Axes &axes_row_b,
const Axes &axes_col_b) {
2520 assert(a.
rank() == axes_row_a.
size() + axes_col_a.
size());
2521 assert(b.
rank() == axes_row_b.
size() + axes_col_b.
size());
2522 assert(axes_row_a.
size() > 0);
2523 assert(axes_col_a.
size() > 0);
2524 assert(axes_row_b.
size() > 0);
2525 assert(axes_col_b.
size() >= 0);
2529 size_t rank_row_a = axes_row_a.
size();
2530 size_t rank_col_a = axes_col_a.
size();
2531 size_t rank_row_b = axes_row_b.
size();
2532 size_t rank_col_b = axes_col_b.
size();
2533 Axes axes_a = axes_row_a + axes_col_a;
2534 Axes axes_b = axes_row_b + axes_col_b;
2544 shape_x.
resize(rank_col_a + rank_col_b);
2545 for (
size_t i = 0; i < rank_col_a; ++i) shape_x[i] = shape_a[i + rank_row_a];
2546 for (
size_t i = 0; i < rank_col_b; ++i)
2547 shape_x[i + rank_col_a] = shape_b[i + rank_row_b];
2556 template <
template <
typename>
class Matrix,
typename C>
2561 template <
template <
typename>
class Matrix,
typename C>
2563 return (rhs *= -1.0);
2566 template <
template <
typename>
class Matrix,
typename C>
2569 return (lhs += rhs);
2572 template <
template <
typename>
class Matrix,
typename C>
2575 return (lhs -= rhs);
2578 template <
template <
typename>
class Matrix,
typename C,
typename D>
2580 return (lhs *= rhs);
2583 template <
template <
typename>
class Matrix,
typename C,
typename D>
2585 return (lhs /= rhs);
2588 template <
template <
typename>
class Matrix,
typename C,
typename D>
2590 return (rhs *= lhs);
2594 template <
template <
typename>
class Matrix,
typename C>
2599 template <
template <
typename>
class Matrix,
typename C>
2604 template <
template <
typename>
class Matrix,
typename C>
2609 template <
template <
typename>
class Matrix,
typename C>
2615 template <
template <
typename>
class Matrix>
2616 inline Tensor<Matrix, double>
sqrt(Tensor<Matrix, double> t) {
2617 return t.map(
static_cast<double (*)(
double)
>(&
std::sqrt));
2619 template <
template <
typename>
class Matrix>
2620 inline Tensor<Matrix, complex>
sqrt(Tensor<Matrix, complex> t) {
2623 template <
template <
typename>
class Matrix>
2624 inline Tensor<Matrix, double>
conj(Tensor<Matrix, double> t) {
2627 template <
template <
typename>
class Matrix>
2628 inline Tensor<Matrix, complex>
conj(Tensor<Matrix, complex> t) {
2638 template <
template <
typename>
class Matrix,
typename C>
2640 std::size_t dim = t.
ndim();
2644 std::vector<std::size_t> accum(dim + 1, 1);
2645 for (
size_t d = dim; d != 0; --d) accum[d - 1] = accum[d] *
shape[d - 1];
2647 std::vector<std::size_t> idx(dim);
2648 for (
size_t i = 0; i < size; ++i) {
2649 for (
size_t d = 0; d < dim; ++d) idx[d] = (i % accum[d]) / accum[d + 1];
2650 if (idx[dim - 1] == 0) {
2652 for (
size_t d = dim; d != 0 && idx[d - 1] == 0; --d) ++count;
2653 for (
size_t i = 0; i < dim - count; ++i) out <<
' ';
2654 for (
size_t i = 0; i < count; ++i) out <<
'[';
2659 out <<
' ' << val <<
' ';
2661 if (idx[dim - 1] ==
shape[dim - 1] - 1) {
2663 for (
size_t d = dim; d != 0 && idx[d - 1] ==
shape[d - 1] - 1; --d) ++count;
2664 for (
size_t i = 0; i < count; ++i) out <<
']';
2666 for (
size_t i = 0; i < count; ++i) out <<
'\n';
2674 for (
size_t d = 0; d < dim; ++d) out <<
'[';
2675 out <<
" distributed tensor ... ";
2676 for (
size_t d = 0; d < dim; ++d) out <<
']';
void resize(size_t n)
Definition: index.hpp:81
std::ostream & operator<<(std::ostream &os, const Index &idx)
Definition: index.cc:71
void assign(size_t n, size_t j[])
Definition: index.cc:37
Index operator+(const Index &lhs, const Index &rhs)
Joint two indices.
Definition: index.cc:86
void push(size_t i)
Definition: index.hpp:80
void sort()
Definition: index.cc:42
size_t size() const
Definition: index.hpp:79
Tensor class. The main object of mptensor.
Definition: tensor.hpp:54
void print_info(std::ostream &out, const std::string &tag="") const
Output information of tensor.
Definition: tensor_impl.hpp:424
size_t rank() const
Rank of tensor.
Definition: tensor_impl.hpp:164
void global_index_fast(size_t i, Index &idx) const
Convert local index to global index fast.
Definition: tensor_impl.hpp:525
size_t ndim() const
Rank of tensor.
Definition: tensor_impl.hpp:173
void prep_local_to_global() const
Preprocess for fast conversion from local index to global one.
Definition: tensor_impl.hpp:258
void local_position_fast(size_t g_row, size_t g_col, int &comm_rank, size_t &local_idx) const
Definition: tensor_impl.hpp:376
Tensor< Matrix, C > & map(UnaryOperation op)
Apply a unary operation to each element.
Definition: tensor_impl.hpp:1026
void prep_global_to_local() const
Preprocess for fast conversion from global index to local one.
Definition: tensor_impl.hpp:252
const Matrix< C > & get_matrix() const
distributed Matrix
Definition: tensor_impl.hpp:203
void local_position(const Index &idx, int &comm_rank, size_t &local_idx) const
Calculate rank which has the given global index and its local index.
Definition: tensor_impl.hpp:584
void make_l2g_map() const
Preprocess for fast conversion from local index to global one.
Definition: tensor_impl.hpp:264
size_t local_size() const
Size of local storage.
Definition: tensor_impl.hpp:179
std::vector< C > flatten()
Return a copy of the flattened vector.
Definition: tensor_impl.hpp:971
int get_comm_rank() const
Rank of process.
Definition: tensor_impl.hpp:228
int get_comm_size() const
Size of communicator.
Definition: tensor_impl.hpp:222
const Axes & get_axes_map() const
Map of axes for lazy evaluation of transpose.
Definition: tensor_impl.hpp:197
Index global_index(size_t i) const
Convert local index to global index.
Definition: tensor_impl.hpp:495
const comm_type & get_comm() const
Communicator.
Definition: tensor_impl.hpp:216
Tensor< Matrix, C > & transpose(const Axes &axes)
Transposition of tensor with lazy evaluation.
Definition: tensor_impl.hpp:667
scalapack::Matrix< double >::comm_type comm_type
type of communicator.
Definition: tensor.hpp:58
const Shape & shape() const
Shape of tensor.
Definition: tensor_impl.hpp:158
size_t get_upper_rank() const
Upper rank for matrix representation.
Definition: tensor_impl.hpp:185
void global_index_l2g_map_transpose(size_t lindex, const size_t axes_trans[], size_t index_new[]) const
Convert local index to global index of transposed tensor using l2g_map.
Definition: tensor_impl.hpp:353
bool get_value(const Index &idx, C &val) const
Get an element.
Definition: tensor_impl.hpp:552
int matrix_eigh(Matrix< C > &a, std::vector< double > &s)
Eigenvalues of a hermite (symmetric) matrix.
Define the type of a complex number.
Tensor< Matrix, C > operator*(Tensor< Matrix, C > lhs, D rhs)
Tensor-scalar multiplication.
Definition: tensor_impl.hpp:2579
Tensor< Matrix, C > operator/(Tensor< Matrix, C > lhs, D rhs)
Scalar division.
Definition: tensor_impl.hpp:2584
int eig(const Tensor< Matrix, C > &a, std::vector< complex > &eigval, Tensor< Matrix, complex > &eigvec)
Compute the eigenvalues and eigenvectors of a general matrix (rank-2 tensor)
Definition: tensor_impl.hpp:2295
int svd(const Tensor< Matrix, C > &a, std::vector< double > &s)
Singular value decomposition for rank-2 tensor (matrix)
Definition: tensor_impl.hpp:1722
int eigh(const Tensor< Matrix, C > &a, std::vector< double > &eigval, Tensor< Matrix, C > &eigvec)
Definition: tensor_impl.hpp:2071
int qr(const Tensor< Matrix, C > &a, Tensor< Matrix, C > &q, Tensor< Matrix, C > &r)
QR decomposition of matrix (rank-2 tensor)
Definition: tensor_impl.hpp:1974
int psvd(const Tensor< Matrix, C > &a, std::vector< double > &s, const size_t target_rank)
Partial SVD for rank-2 tensor (matrix)
Definition: tensor_impl.hpp:1866
Tensor< Matrix, C > tensordot(const Tensor< Matrix, C > &a, const Tensor< Matrix, C > &b, const Axes &axes_a, const Axes &axes_b)
Compute tensor dot product.
Definition: tensor_impl.hpp:1648
Tensor< Matrix, C > contract(const Tensor< Matrix, C > &a, const Axes &axes_1, const Axes &axes_2)
Partial trace of tensor.
Definition: tensor_impl.hpp:1519
Tensor< Matrix, C > kron(const Tensor< Matrix, C > &a, const Tensor< Matrix, C > &b)
Compute the Kronecker product.
Definition: tensor_impl.hpp:1612
C trace(const Tensor< Matrix, C > &a)
Trace of matrix (rank-2 tensor)
Definition: tensor_impl.hpp:1409
int solve(const Tensor< Matrix, C > &a, const std::vector< C > &b, std::vector< C > &x)
Solve linear equation .
Definition: tensor_impl.hpp:2447
Tensor< Matrix, C > sqrt(Tensor< Matrix, C > t)
Take square-root of each element.
Tensor< Matrix, C > conj(Tensor< Matrix, C > t)
Take conjugate of each element.
Tensor< Matrix, C > transpose(Tensor< Matrix, C > a, const Axes &axes)
Transposition of tensor with lazy evaluation.
Definition: tensor_impl.hpp:1041
Tensor< Matrix, C > slice(const Tensor< Matrix, C > &a, size_t n_axes, size_t i_begin, size_t i_end)
Slice a tensor.
Definition: tensor_impl.hpp:1215
Tensor< Matrix, C > reshape(const Tensor< Matrix, C > &a, const Shape &shape_new)
Change the shape of tensor.
Definition: tensor_impl.hpp:1149
Tensor< Matrix, C > extend(const Tensor< Matrix, C > &a, const Shape &shape_new)
Extend the size of a tensor.
Definition: tensor_impl.hpp:1363
Tensor()
Default constructor of tensor.
Definition: tensor_impl.hpp:70
header file of Index class
Index(size_t j0)
Definition: index_constructor.hpp:11
List of header files for matrix classes.
mptensor::complex complex
Definition: matrix_lapack.cc:36
bool check_total_size(const Shape &s1, const Shape &s2)
Definition: tensor.cc:49
bool check_trace_axes(const Axes &axes_1, const Axes &axes_2, size_t rank)
Definition: tensor.cc:86
bool check_extend(const Shape &s_old, const Shape &s_new)
Definition: tensor.cc:57
bool check_svd_axes(const Axes &axes_row, const Axes &axes_col, size_t rank)
Definition: tensor.cc:76
bool check_contract_axes(const Axes &axes_1, const Axes &axes_2, size_t rank)
Definition: tensor.cc:114
bool check_transpose_axes(const Axes &axes, size_t rank)
Definition: tensor.cc:66
bool check_trace_axes(const Axes &axes_a, const Axes &axes_b, const Shape &shape_a, const Shape &shape_b)
Definition: tensor.cc:95
bool check_square(const Shape &shape, size_t urank)
Definition: tensor.cc:125
constexpr bool debug
Definition: io_helper.hpp:46
int matrix_eig(Matrix< C > &a, std::vector< complex > &s, Matrix< complex > &u)
void matrix_product(const Matrix< C > &a, const Matrix< C > &b, Matrix< C > &c)
double min(const Matrix< C > &a)
double max(const Matrix< C > &a)
C matrix_trace(const Matrix< C > &a)
Definition: matrix_lapack_impl.hpp:374
int matrix_solve(Matrix< C > &a, Matrix< C > &b)
void replace_matrix_data(const Matrix< C > &M, const std::vector< int > &dest_rank, const std::vector< size_t > &local_position, Matrix< C > &M_new)
Definition: matrix_lapack_impl.hpp:323
double max_abs(const Matrix< C > &a)
Definition: matrix_lapack_impl.hpp:388
int matrix_svd(Matrix< C > &a, Matrix< C > &u, std::vector< double > &s, Matrix< C > &v)
double min_abs(const Matrix< C > &a)
Definition: matrix_lapack_impl.hpp:398
int matrix_qr(Matrix< C > &a, Matrix< C > &r)
void sum_matrix_data(const Matrix< C > &M, const std::vector< int > &dest_rank, const std::vector< size_t > &local_position, Matrix< C > &M_new)
Definition: matrix_lapack_impl.hpp:357
Definition: complex.hpp:34
Index range(const size_t start, const size_t stop)
Create an increasing sequence. it is similar to range() in python.
Definition: index.cc:91
Index Shape
Definition: tensor.hpp:46
Index Axes
Definition: tensor.hpp:45
bool is_no_transpose(const Axes &axes, const Axes &axes_map, size_t rank)
Definition: tensor.cc:35
tuple shape
Definition: output.py:28
double operator-(Timer &t1, Timer &t0)
Definition: timer.hpp:64