unsigned char tr_info_list_pr_dof(struct tr_info_list *list, unsigned char addr[]){ unsigned char nbr_dof = tr_get_data_k(); struct tr_info *temp_info = tr_info_find_addr(list, addr); if(temp_info != NULL){ unsigned char src_k = n_to_k(tr_get_data_n(), temp_info->total_num, temp_info->rcv_num[0]); nbr_dof = (nbr_dof > src_k ? nbr_dof - src_k : 0); } return nbr_dof; }
inline TR TrX(const T1& rho1, arma::uvec sys, arma::uvec dim) { const auto& p = as_Mat(rho1); bool checkV = true; if (p.n_cols == 1) checkV = false; #ifndef QICLIB_NO_DEBUG if (p.n_elem == 0) throw Exception("qic::TrX", Exception::type::ZERO_SIZE); if (checkV) if (p.n_rows != p.n_cols) throw Exception("qic::TrX", Exception::type::MATRIX_NOT_SQUARE_OR_CVECTOR); if (dim.n_elem == 0 || arma::any(dim == 0)) throw Exception("qic::TrX", Exception::type::INVALID_DIMS); if (arma::prod(dim) != p.n_rows) throw Exception("qic::TrX", Exception::type::DIMS_MISMATCH_MATRIX); if (dim.n_elem < sys.n_elem || arma::any(sys == 0) || arma::any(sys > dim.n_elem) || sys.n_elem != arma::find_unique(sys, false).eval().n_elem) throw Exception("qic::TrX", Exception::type::INVALID_SUBSYS); #endif if (sys.n_elem == dim.n_elem) return {arma::trace(p)}; _internal::dim_collapse_sys(dim, sys); const arma::uword n = dim.n_elem; const arma::uword m = sys.n_elem; arma::uvec keep(n - m); arma::uword keep_count(0); for (arma::uword run = 0; run < n; ++run) { if (!arma::any(sys == run + 1)) { keep.at(keep_count) = run + 1; ++keep_count; } } arma::uword dimtrace = arma::prod(dim(sys - 1)); arma::uword dimkeep = p.n_rows / dimtrace; arma::uvec product(n, arma::fill::ones); for (arma::sword i = n - 2; i > -1; --i) product.at(i) = product.at(i + 1) * dim.at(i + 1); arma::uvec productr(n - m, arma::fill::ones); for (arma::sword i = n - m - 2; i > -1; --i) productr.at(i) = productr.at(i + 1) * dim.at(keep.at(i + 1) - 1); arma::Mat<trait::eT<T1> > tr_p(dimkeep, dimkeep, arma::fill::zeros); const arma::uword loop_no = 2 * n; arma::uword* loop_counter = new arma::uword[loop_no + 1]; arma::uword* MAX = new arma::uword[loop_no + 1]; for (arma::uword i = 0; i < n; ++i) { MAX[i] = dim.at(i); if (arma::any(sys == (i + 1))) MAX[i + n] = 1; else MAX[i + n] = dim.at(i); } MAX[loop_no] = 2; for (arma::uword i = 0; i < loop_no + 1; ++i) loop_counter[i] = 0; arma::uword p1 = 0; while (loop_counter[loop_no] == 0) { arma::uword I(0), J(0), K(0), L(0), n_to_k(0); for (arma::uword i = 0; i < n; ++i) { if (arma::any(sys == i + 1)) { I += product.at(i) * loop_counter[i]; J += product.at(i) * loop_counter[i]; } else { I += product.at(i) * loop_counter[i]; J += product.at(i) * loop_counter[i + n]; } if (arma::any(keep == i + 1)) { K += productr.at(n_to_k) * loop_counter[i]; L += productr.at(n_to_k) * loop_counter[i + n]; ++n_to_k; } } tr_p.at(K, L) += checkV ? p.at(I, J) : p.at(I) * std::conj(p.at(J)); ++loop_counter[0]; while (loop_counter[p1] == MAX[p1]) { loop_counter[p1] = 0; loop_counter[++p1]++; if (loop_counter[p1] != MAX[p1]) p1 = 0; } } delete[] loop_counter; delete[] MAX; return tr_p; }