44 template <
typename Derived>
45 dyn_mat<typename Derived::Scalar>
46 transpose(
const Eigen::MatrixBase<Derived>& A) {
47 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
52 if (!internal::check_nonzero_size(rA))
53 throw exception::ZeroSize(
"qpp::transpose()");
56 return rA.transpose();
66 template <
typename Derived>
67 dyn_mat<typename Derived::Scalar>
68 conjugate(
const Eigen::MatrixBase<Derived>& A) {
69 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
74 if (!internal::check_nonzero_size(rA))
75 throw exception::ZeroSize(
"qpp::conjugate()");
78 return rA.conjugate();
88 template <
typename Derived>
89 dyn_mat<typename Derived::Scalar> adjoint(
const Eigen::MatrixBase<Derived>& A) {
90 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
95 if (!internal::check_nonzero_size(rA))
96 throw exception::ZeroSize(
"qpp::adjoint()");
109 template <
typename Derived>
110 dyn_mat<typename Derived::Scalar> inverse(
const Eigen::MatrixBase<Derived>& A) {
111 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
116 if (!internal::check_nonzero_size(rA))
117 throw exception::ZeroSize(
"qpp::inverse()");
129 template <
typename Derived>
130 typename Derived::Scalar trace(
const Eigen::MatrixBase<Derived>& A) {
131 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
136 if (!internal::check_nonzero_size(rA))
137 throw exception::ZeroSize(
"qpp::trace()");
150 template <
typename Derived>
151 typename Derived::Scalar det(
const Eigen::MatrixBase<Derived>& A) {
152 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
157 if (!internal::check_nonzero_size(rA))
158 throw exception::ZeroSize(
"qpp::det()");
161 return rA.determinant();
173 template <
typename Derived>
174 typename Derived::Scalar logdet(
const Eigen::MatrixBase<Derived>& A) {
175 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
180 if (!internal::check_nonzero_size(rA))
181 throw exception::ZeroSize(
"qpp::logdet()");
184 if (!internal::check_square_mat(rA))
185 throw exception::MatrixNotSquare(
"qpp::logdet()");
188 Eigen::PartialPivLU<dyn_mat<typename Derived::Scalar>> lu(rA);
189 dyn_mat<typename Derived::Scalar> U =
190 lu.matrixLU().template triangularView<Eigen::Upper>();
191 typename Derived::Scalar result = std::log(U(0, 0));
193 for (idx i = 1; i < static_cast<idx>(rA.rows()); ++i)
194 result += std::log(U(i, i));
206 template <
typename Derived>
207 typename Derived::Scalar sum(
const Eigen::MatrixBase<Derived>& A) {
208 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
213 if (!internal::check_nonzero_size(rA))
214 throw exception::ZeroSize(
"qpp::sum()");
227 template <
typename Derived>
228 typename Derived::Scalar prod(
const Eigen::MatrixBase<Derived>& A) {
229 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
234 if (!internal::check_nonzero_size(rA))
235 throw exception::ZeroSize(
"qpp::prod()");
247 template <
typename Derived>
248 double norm(
const Eigen::MatrixBase<Derived>& A) {
249 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
254 if (!internal::check_nonzero_size(rA))
255 throw exception::ZeroSize(
"qpp::norm()");
259 return (rA.template cast<cplx>()).norm();
268 template <
typename Derived>
269 dyn_mat<typename Derived::Scalar>
270 normalize(
const Eigen::MatrixBase<Derived>& A) {
271 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
276 if (!internal::check_nonzero_size(rA))
277 throw exception::ZeroSize(
"qpp::normalize()");
280 dyn_mat<typename Derived::Scalar> result;
282 if (internal::check_cvector(rA) || internal::check_rvector(rA)) {
283 double normA = norm(rA);
286 throw std::overflow_error(
"Division by zero!");
288 std::cerr <<
"In qpp::normalize()\n";
292 }
else if (internal::check_square_mat(rA)) {
293 typename Derived::Scalar traceA = trace(rA);
295 if (std::abs(traceA) == 0)
296 throw std::overflow_error(
"Division by zero!");
298 std::cerr <<
"In qpp::normalize()\n";
301 result = rA / trace(rA);
303 throw exception::MatrixNotSquareNorVector(
"qpp::normalize()");
316 template <
typename Derived>
317 std::pair<dyn_col_vect<cplx>, cmat> eig(
const Eigen::MatrixBase<Derived>& A) {
318 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
323 if (!internal::check_nonzero_size(rA))
324 throw exception::ZeroSize(
"qpp::eig()");
327 if (!internal::check_square_mat(rA))
328 throw exception::MatrixNotSquare(
"qpp::eig()");
331 Eigen::ComplexEigenSolver<cmat> es(rA.template cast<cplx>());
333 return std::make_pair(es.eigenvalues(), es.eigenvectors());
343 template <
typename Derived>
344 dyn_col_vect<cplx> evals(
const Eigen::MatrixBase<Derived>& A) {
345 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
350 if (!internal::check_nonzero_size(rA))
351 throw exception::ZeroSize(
"qpp::evals()");
354 if (!internal::check_square_mat(rA))
355 throw exception::MatrixNotSquare(
"qpp::evals()");
358 return eig(rA).first;
368 template <
typename Derived>
369 cmat evects(
const Eigen::MatrixBase<Derived>& A) {
370 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
375 if (!internal::check_nonzero_size(rA))
376 throw exception::ZeroSize(
"qpp::evects()");
379 if (!internal::check_square_mat(rA))
380 throw exception::MatrixNotSquare(
"qpp::evects()");
383 Eigen::ComplexEigenSolver<cmat> es(rA.template cast<cplx>());
385 return eig(rA).second;
396 template <
typename Derived>
397 std::pair<dyn_col_vect<double>, cmat>
398 heig(
const Eigen::MatrixBase<Derived>& A) {
399 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
404 if (!internal::check_nonzero_size(rA))
405 throw exception::ZeroSize(
"qpp::heig()");
408 if (!internal::check_square_mat(rA))
409 throw exception::MatrixNotSquare(
"qpp::heig()");
412 Eigen::SelfAdjointEigenSolver<cmat> es(rA.template cast<cplx>());
414 return std::make_pair(es.eigenvalues(), es.eigenvectors());
424 template <
typename Derived>
425 dyn_col_vect<double> hevals(
const Eigen::MatrixBase<Derived>& A) {
426 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
431 if (!internal::check_nonzero_size(rA))
432 throw exception::ZeroSize(
"qpp::hevals()");
435 if (!internal::check_square_mat(rA))
436 throw exception::MatrixNotSquare(
"qpp::hevals()");
439 return heig(rA).first;
449 template <
typename Derived>
450 cmat hevects(
const Eigen::MatrixBase<Derived>& A) {
451 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
456 if (!internal::check_nonzero_size(rA))
457 throw exception::ZeroSize(
"qpp::hevects()");
460 if (!internal::check_square_mat(rA))
461 throw exception::MatrixNotSquare(
"qpp::hevects()");
464 return heig(rA).second;
476 template <
typename Derived>
477 std::tuple<cmat, dyn_col_vect<double>, cmat>
479 svd(
const Eigen::MatrixBase<Derived>& A) {
480 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
485 if (!internal::check_nonzero_size(rA))
486 throw exception::ZeroSize(
"qpp::svd()");
489 Eigen::JacobiSVD<dyn_mat<typename Derived::Scalar>> sv(
490 rA, Eigen::DecompositionOptions::ComputeFullU |
491 Eigen::DecompositionOptions::ComputeFullV);
493 return std::make_tuple(sv.matrixU(), sv.singularValues(), sv.matrixV());
503 template <
typename Derived>
504 dyn_col_vect<double> svals(
const Eigen::MatrixBase<Derived>& A) {
505 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
510 if (!internal::check_nonzero_size(rA))
511 throw exception::ZeroSize(
"qpp::svals()");
514 Eigen::JacobiSVD<dyn_mat<typename Derived::Scalar>> sv(rA);
516 return sv.singularValues();
526 template <
typename Derived>
527 cmat svdU(
const Eigen::MatrixBase<Derived>& A) {
528 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
533 if (!internal::check_nonzero_size(rA))
534 throw exception::ZeroSize(
"qpp::svdU()");
537 Eigen::JacobiSVD<dyn_mat<typename Derived::Scalar>> sv(
538 rA, Eigen::DecompositionOptions::ComputeFullU);
550 template <
typename Derived>
551 cmat svdV(
const Eigen::MatrixBase<Derived>& A) {
552 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
557 if (!internal::check_nonzero_size(rA))
558 throw exception::ZeroSize(
"qpp::svdV()");
561 Eigen::JacobiSVD<dyn_mat<typename Derived::Scalar>> sv(
562 rA, Eigen::DecompositionOptions::ComputeFullV);
576 template <
typename Derived>
577 cmat funm(
const Eigen::MatrixBase<Derived>& A, cplx (*f)(
const cplx&)) {
578 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
583 if (!internal::check_nonzero_size(rA))
584 throw exception::ZeroSize(
"qpp::funm()");
587 if (!internal::check_square_mat(rA))
588 throw exception::MatrixNotSquare(
"qpp::funm()");
591 Eigen::ComplexEigenSolver<cmat> es(rA.template cast<cplx>());
592 cmat evects = es.eigenvectors();
593 cmat evals = es.eigenvalues();
594 for (idx i = 0; i < static_cast<idx>(evals.rows()); ++i)
595 evals(i) = (*f)(evals(i));
597 cmat evalsdiag = evals.asDiagonal();
599 return evects * evalsdiag * evects.inverse();
608 template <
typename Derived>
609 cmat sqrtm(
const Eigen::MatrixBase<Derived>& A) {
610 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
615 if (!internal::check_nonzero_size(rA))
616 throw exception::ZeroSize(
"qpp::sqrtm()");
619 if (!internal::check_square_mat(rA))
620 throw exception::MatrixNotSquare(
"qpp::sqrtm()");
623 return funm(rA, &std::sqrt);
632 template <
typename Derived>
633 cmat absm(
const Eigen::MatrixBase<Derived>& A) {
634 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
639 if (!internal::check_nonzero_size(rA))
640 throw exception::ZeroSize(
"qpp::absm()");
643 if (!internal::check_square_mat(rA))
644 throw exception::MatrixNotSquare(
"qpp::absm()");
647 return sqrtm(adjoint(rA) * rA);
656 template <
typename Derived>
657 cmat expm(
const Eigen::MatrixBase<Derived>& A) {
658 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
663 if (!internal::check_nonzero_size(rA))
664 throw exception::ZeroSize(
"qpp::expm()");
667 if (!internal::check_square_mat(rA))
668 throw exception::MatrixNotSquare(
"qpp::expm()");
671 return funm(rA, &std::exp);
680 template <
typename Derived>
681 cmat logm(
const Eigen::MatrixBase<Derived>& A) {
682 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
687 if (!internal::check_nonzero_size(rA))
688 throw exception::ZeroSize(
"qpp::logm()");
691 if (!internal::check_square_mat(rA))
692 throw exception::MatrixNotSquare(
"qpp::logm()");
695 return funm(rA, &std::log);
704 template <
typename Derived>
705 cmat sinm(
const Eigen::MatrixBase<Derived>& A) {
706 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
711 if (!internal::check_nonzero_size(rA))
712 throw exception::ZeroSize(
"qpp::sinm()");
715 if (!internal::check_square_mat(rA))
716 throw exception::MatrixNotSquare(
"qpp::sinm()");
719 return funm(rA, &std::sin);
728 template <
typename Derived>
729 cmat cosm(
const Eigen::MatrixBase<Derived>& A) {
730 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
735 if (!internal::check_nonzero_size(rA))
736 throw exception::ZeroSize(
"qpp::cosm()");
739 if (!internal::check_square_mat(rA))
740 throw exception::MatrixNotSquare(
"qpp::cosm()");
743 return funm(rA, &std::cos);
757 template <
typename Derived>
758 cmat spectralpowm(
const Eigen::MatrixBase<Derived>& A,
const cplx z) {
759 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
764 if (!internal::check_nonzero_size(rA))
765 throw exception::ZeroSize(
"qpp::spectralpowm()");
768 if (!internal::check_square_mat(rA))
769 throw exception::MatrixNotSquare(
"qpp::spectralpowm()");
773 if (real(z) == 0 && imag(z) == 0)
774 return cmat::Identity(rA.rows(), rA.rows());
776 Eigen::ComplexEigenSolver<cmat> es(rA.template cast<cplx>());
777 cmat evects = es.eigenvectors();
778 cmat evals = es.eigenvalues();
779 for (idx i = 0; i < static_cast<idx>(evals.rows()); ++i)
780 evals(i) = std::pow(evals(i), z);
782 cmat evalsdiag = evals.asDiagonal();
784 return evects * evalsdiag * evects.inverse();
799 template <
typename Derived>
800 dyn_mat<typename Derived::Scalar> powm(
const Eigen::MatrixBase<Derived>& A,
805 if (!internal::check_nonzero_size(A))
806 throw exception::ZeroSize(
"qpp::powm()");
809 if (!internal::check_square_mat(A))
810 throw exception::MatrixNotSquare(
"qpp::powm()");
817 dyn_mat<typename Derived::Scalar> result =
818 dyn_mat<typename Derived::Scalar>::Identity(A.rows(), A.rows());
824 dyn_mat<typename Derived::Scalar> cA = A.derived();
827 for (; n > 0; n /= 2) {
829 result = (result * cA).eval();
830 cA = (cA * cA).eval();
844 template <
typename Derived>
845 double schatten(
const Eigen::MatrixBase<Derived>& A,
double p) {
846 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
851 if (!internal::check_nonzero_size(rA))
852 throw exception::ZeroSize(
"qpp::schatten()");
854 throw exception::OutOfRange(
"qpp::schatten()");
860 const dyn_col_vect<double> sv = svals(rA);
862 for (idx i = 0; i < static_cast<idx>(sv.rows()); ++i)
863 result += std::pow(sv[i], p);
865 return std::pow(result, 1. / p);
878 template <
typename OutputScalar,
typename Derived>
879 dyn_mat<OutputScalar>
880 cwise(
const Eigen::MatrixBase<Derived>& A,
881 OutputScalar (*f)(
const typename Derived::Scalar&)) {
882 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
887 if (!internal::check_nonzero_size(rA))
888 throw exception::ZeroSize(
"qpp::cwise()");
891 dyn_mat<OutputScalar> result(rA.rows(), rA.cols());
894 #pragma omp parallel for collapse(2) 895 #endif // WITH_OPENMP_ 897 for (idx j = 0; j < static_cast<idx>(rA.cols()); ++j)
898 for (idx i = 0; i < static_cast<idx>(rA.rows()); ++i)
899 result(i, j) = (*f)(rA(i, j));
915 template <
typename T>
916 dyn_mat<typename T::Scalar> kron(
const T& head) {
929 template <
typename T,
typename... Args>
930 dyn_mat<typename T::Scalar> kron(
const T& head,
const Args&... tail) {
931 return internal::kron2(head, kron(tail...));
942 template <
typename Derived>
943 dyn_mat<typename Derived::Scalar> kron(
const std::vector<Derived>& As) {
947 throw exception::ZeroSize(
"qpp::kron()");
949 for (
auto&& elem : As)
950 if (!internal::check_nonzero_size(elem))
951 throw exception::ZeroSize(
"qpp::kron()");
954 dyn_mat<typename Derived::Scalar> result = As[0].derived();
955 for (idx i = 1; i < As.size(); ++i) {
956 result = kron(result, As[i]);
973 template <
typename Derived>
974 dyn_mat<typename Derived::Scalar>
975 kron(
const std::initializer_list<Derived>& As) {
976 return kron(std::vector<Derived>(As));
988 template <
typename Derived>
989 dyn_mat<typename Derived::Scalar> kronpow(
const Eigen::MatrixBase<Derived>& A,
991 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
996 if (!internal::check_nonzero_size(rA))
997 throw exception::ZeroSize(
"qpp::kronpow()");
1001 throw exception::OutOfRange(
"qpp::kronpow()");
1004 std::vector<dyn_mat<typename Derived::Scalar>> As(n, rA);
1020 template <
typename T>
1021 dyn_mat<typename T::Scalar> dirsum(
const T& head) {
1034 template <
typename T,
typename... Args>
1035 dyn_mat<typename T::Scalar> dirsum(
const T& head,
const Args&... tail) {
1036 return internal::dirsum2(head, dirsum(tail...));
1047 template <
typename Derived>
1048 dyn_mat<typename Derived::Scalar> dirsum(
const std::vector<Derived>& As) {
1052 throw exception::ZeroSize(
"qpp::dirsum()");
1054 for (
auto&& elem : As)
1055 if (!internal::check_nonzero_size(elem))
1056 throw exception::ZeroSize(
"qpp::dirsum()");
1059 idx total_rows = 0, total_cols = 0;
1060 for (idx i = 0; i < As.size(); ++i) {
1061 total_rows +=
static_cast<idx
>(As[i].rows());
1062 total_cols +=
static_cast<idx
>(As[i].cols());
1064 dyn_mat<typename Derived::Scalar> result =
1065 dyn_mat<typename Derived::Scalar>::Zero(total_rows, total_cols);
1067 idx cur_row = 0, cur_col = 0;
1068 for (idx i = 0; i < As.size(); ++i) {
1069 result.block(cur_row, cur_col, As[i].rows(), As[i].cols()) = As[i];
1070 cur_row +=
static_cast<idx
>(As[i].rows());
1071 cur_col +=
static_cast<idx
>(As[i].cols());
1088 template <
typename Derived>
1089 dyn_mat<typename Derived::Scalar>
1090 dirsum(
const std::initializer_list<Derived>& As) {
1091 return dirsum(std::vector<Derived>(As));
1103 template <
typename Derived>
1104 dyn_mat<typename Derived::Scalar> dirsumpow(
const Eigen::MatrixBase<Derived>& A,
1106 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1111 if (!internal::check_nonzero_size(rA))
1112 throw exception::ZeroSize(
"qpp::dirsumpow()");
1116 throw exception::OutOfRange(
"qpp::dirsumpow()");
1119 std::vector<dyn_mat<typename Derived::Scalar>> As(n, rA);
1135 template <
typename Derived>
1136 dyn_mat<typename Derived::Scalar> reshape(
const Eigen::MatrixBase<Derived>& A,
1137 idx rows, idx cols) {
1138 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1140 idx Arows =
static_cast<idx
>(rA.rows());
1141 idx Acols =
static_cast<idx
>(rA.cols());
1146 if (!internal::check_nonzero_size(rA))
1147 throw exception::ZeroSize(
"qpp::reshape()");
1149 if (Arows * Acols != rows * cols)
1150 throw exception::DimsMismatchMatrix(
"qpp::reshape()");
1153 return Eigen::Map<dyn_mat<typename Derived::Scalar>>(
1154 const_cast<typename Derived::Scalar*
>(rA.data()), rows, cols);
1169 template <
typename Derived1,
typename Derived2>
1170 dyn_mat<typename Derived1::Scalar> comm(
const Eigen::MatrixBase<Derived1>& A,
1171 const Eigen::MatrixBase<Derived2>& B) {
1172 const dyn_mat<typename Derived1::Scalar>& rA = A.derived();
1173 const dyn_mat<typename Derived2::Scalar>& rB = B.derived();
1178 if (!std::is_same<
typename Derived1::Scalar,
1179 typename Derived2::Scalar>::value)
1180 throw exception::TypeMismatch(
"qpp::comm()");
1183 if (!internal::check_nonzero_size(rA) || !internal::check_nonzero_size(rB))
1184 throw exception::ZeroSize(
"qpp::comm()");
1187 if (!internal::check_square_mat(rA) || !internal::check_square_mat(rB))
1188 throw exception::MatrixNotSquare(
"qpp::comm()");
1191 if (rA.rows() != rB.rows())
1192 throw exception::DimsNotEqual(
"qpp::comm()");
1195 return rA * rB - rB * rA;
1210 template <
typename Derived1,
typename Derived2>
1211 dyn_mat<typename Derived1::Scalar>
1212 anticomm(
const Eigen::MatrixBase<Derived1>& A,
1213 const Eigen::MatrixBase<Derived2>& B) {
1214 const dyn_mat<typename Derived1::Scalar>& rA = A.derived();
1215 const dyn_mat<typename Derived2::Scalar>& rB = B.derived();
1220 if (!std::is_same<
typename Derived1::Scalar,
1221 typename Derived2::Scalar>::value)
1222 throw exception::TypeMismatch(
"qpp::anticomm()");
1225 if (!internal::check_nonzero_size(rA) || !internal::check_nonzero_size(rB))
1226 throw exception::ZeroSize(
"qpp::anticomm()");
1229 if (!internal::check_square_mat(rA) || !internal::check_square_mat(rB))
1230 throw exception::MatrixNotSquare(
"qpp::anticomm()");
1233 if (rA.rows() != rB.rows())
1234 throw exception::DimsNotEqual(
"qpp::anticomm()");
1237 return rA * rB + rB * rA;
1249 template <
typename Derived>
1250 dyn_mat<typename Derived::Scalar> prj(
const Eigen::MatrixBase<Derived>& A) {
1251 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1256 if (!internal::check_nonzero_size(rA))
1257 throw exception::ZeroSize(
"qpp::prj()");
1260 if (!internal::check_cvector(rA))
1261 throw exception::MatrixNotCvector(
"qpp::prj()");
1264 double normA = norm(rA);
1266 return rA * adjoint(rA) / (normA * normA);
1268 return dyn_mat<typename Derived::Scalar>::Zero(rA.rows(), rA.rows());
1278 template <
typename Derived>
1279 dyn_mat<typename Derived::Scalar> grams(
const std::vector<Derived>& As) {
1283 if (!internal::check_nonzero_size(As))
1284 throw exception::ZeroSize(
"qpp::grams()");
1286 for (
auto&& elem : As)
1287 if (!internal::check_nonzero_size(elem))
1288 throw exception::ZeroSize(
"qpp::grams()");
1291 if (!internal::check_cvector(As[0]))
1292 throw exception::MatrixNotCvector(
"qpp::grams()");
1295 for (
auto&& elem : As)
1296 if (elem.rows() != As[0].rows() || elem.cols() != 1)
1297 throw exception::DimsNotEqual(
"qpp::grams()");
1300 dyn_mat<typename Derived::Scalar> cut =
1301 dyn_mat<typename Derived::Scalar>::Identity(As[0].rows(), As[0].rows());
1303 dyn_mat<typename Derived::Scalar> vi =
1304 dyn_mat<typename Derived::Scalar>::Zero(As[0].rows(), 1);
1306 std::vector<dyn_mat<typename Derived::Scalar>> outvecs;
1309 for (pos = 0; pos < As.size(); ++pos) {
1310 if (norm(As[pos]) > 0)
1312 outvecs.emplace_back(As[pos]);
1318 for (idx i = pos + 1; i < As.size(); ++i) {
1319 cut -= prj(outvecs[i - 1 - pos]);
1321 outvecs.emplace_back(vi);
1324 dyn_mat<typename Derived::Scalar> result(As[0].rows(), outvecs.size());
1327 for (
auto&& elem : outvecs) {
1328 double normA = norm(elem);
1331 result.col(cnt) = elem / normA;
1336 return result.block(0, 0, As[0].rows(), cnt);
1347 template <
typename Derived>
1348 dyn_mat<typename Derived::Scalar>
1349 grams(
const std::initializer_list<Derived>& As) {
1350 return grams(std::vector<Derived>(As));
1360 template <
typename Derived>
1361 dyn_mat<typename Derived::Scalar> grams(
const Eigen::MatrixBase<Derived>& A) {
1362 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1366 if (!internal::check_nonzero_size(rA))
1367 throw exception::ZeroSize(
"qpp::grams()");
1370 std::vector<dyn_mat<typename Derived::Scalar>> input;
1372 for (idx i = 0; i < static_cast<idx>(rA.cols()); ++i)
1373 input.emplace_back(rA.col(i));
1375 return grams<dyn_mat<typename Derived::Scalar>>(input);
1388 inline std::vector<idx> n2multiidx(idx n,
const std::vector<idx>& dims) {
1391 if (!internal::check_dims(dims))
1392 throw exception::DimsInvalid(
"qpp::n2multiidx()");
1394 if (n >= std::accumulate(std::begin(dims), std::end(dims),
1395 static_cast<idx>(1), std::multiplies<idx>()))
1396 throw exception::OutOfRange(
"qpp::n2multiidx()");
1400 idx result[2 * maxn];
1401 internal::n2multiidx(n, dims.size(), dims.data(), result);
1403 return std::vector<idx>(result, result + dims.size());
1416 inline idx multiidx2n(
const std::vector<idx>& midx,
1417 const std::vector<idx>& dims) {
1420 if (!internal::check_dims(dims))
1421 throw exception::DimsInvalid(
"qpp::multiidx2n()");
1423 for (idx i = 0; i < dims.size(); ++i)
1424 if (midx[i] >= dims[i]) {
1425 throw exception::OutOfRange(
"qpp::multiidx2n()");
1429 return internal::multiidx2n(midx.data(), dims.size(), dims.data());
1445 inline ket mket(
const std::vector<idx>& mask,
const std::vector<idx>& dims) {
1446 idx n = mask.size();
1448 idx D = std::accumulate(std::begin(dims), std::end(dims),
1449 static_cast<idx>(1), std::multiplies<idx>());
1455 throw exception::ZeroSize(
"qpp::mket()");
1457 if (!internal::check_dims(dims))
1458 throw exception::DimsInvalid(
"qpp::mket()");
1460 if (mask.size() != dims.size())
1461 throw exception::SubsysMismatchDims(
"qpp::mket()");
1463 for (idx i = 0; i < n; ++i)
1464 if (mask[i] >= dims[i])
1465 throw exception::SubsysMismatchDims(
"qpp::mket()");
1468 ket result = ket::Zero(D);
1469 idx pos = multiidx2n(mask, dims);
1488 inline ket mket(
const std::vector<idx>& mask, idx d = 2) {
1489 idx n = mask.size();
1490 idx D =
static_cast<idx
>(std::llround(std::pow(d, n)));
1496 throw exception::ZeroSize(
"qpp::mket()");
1500 throw exception::DimsInvalid(
"qpp::mket()");
1503 for (idx i = 0; i < n; ++i)
1505 throw exception::SubsysMismatchDims(
"qpp::mket()");
1508 ket result = ket::Zero(D);
1509 std::vector<idx> dims(n, d);
1510 idx pos = multiidx2n(mask, dims);
1530 inline cmat mprj(
const std::vector<idx>& mask,
const std::vector<idx>& dims) {
1531 idx n = mask.size();
1533 idx D = std::accumulate(std::begin(dims), std::end(dims),
1534 static_cast<idx>(1), std::multiplies<idx>());
1540 throw exception::ZeroSize(
"qpp::mprj()");
1542 if (!internal::check_dims(dims))
1543 throw exception::DimsInvalid(
"qpp::mprj()");
1545 if (mask.size() != dims.size())
1546 throw exception::SubsysMismatchDims(
"qpp::mprj()");
1548 for (idx i = 0; i < n; ++i)
1549 if (mask[i] >= dims[i])
1550 throw exception::SubsysMismatchDims(
"qpp::mprj()");
1553 cmat result = cmat::Zero(D, D);
1554 idx pos = multiidx2n(mask, dims);
1555 result(pos, pos) = 1;
1574 inline cmat mprj(
const std::vector<idx>& mask, idx d = 2) {
1575 idx n = mask.size();
1576 idx D =
static_cast<idx
>(std::llround(std::pow(d, n)));
1582 throw exception::ZeroSize(
"qpp::mprj()");
1586 throw exception::DimsInvalid(
"qpp::mprj()");
1589 for (idx i = 0; i < n; ++i)
1591 throw exception::SubsysMismatchDims(
"qpp::mprj()");
1594 cmat result = cmat::Zero(D, D);
1595 std::vector<idx> dims(n, d);
1596 idx pos = multiidx2n(mask, dims);
1597 result(pos, pos) = 1;
1610 template <
typename InputIterator>
1611 std::vector<double> abssq(InputIterator first, InputIterator last) {
1612 std::vector<double> weights(std::distance(first, last));
1613 std::transform(first, last, std::begin(weights),
1614 [](cplx z) ->
double {
return std::norm(z); });
1625 template <
typename Container>
1627 abssq(
const Container& c,
1628 typename std::enable_if<is_iterable<Container>::value>::type* =
nullptr)
1636 return abssq(std::begin(c), std::end(c));
1645 template <
typename Derived>
1646 std::vector<double> abssq(
const Eigen::MatrixBase<Derived>& A) {
1647 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1652 if (!internal::check_nonzero_size(rA))
1653 throw exception::ZeroSize(
"qpp::abssq()");
1656 return abssq(rA.data(), rA.data() + rA.size());
1667 template <
typename InputIterator>
1668 typename std::iterator_traits<InputIterator>::value_type
1669 sum(InputIterator first, InputIterator last) {
1670 using value_type =
typename std::iterator_traits<InputIterator>::value_type;
1672 return std::accumulate(first, last, static_cast<value_type>(0));
1682 template <
typename Container>
1683 typename Container::value_type
1684 sum(
const Container& c,
1685 typename std::enable_if<is_iterable<Container>::value>::type* =
nullptr) {
1686 return sum(std::begin(c), std::end(c));
1697 template <
typename InputIterator>
1698 typename std::iterator_traits<InputIterator>::value_type
1699 prod(InputIterator first, InputIterator last) {
1700 using value_type =
typename std::iterator_traits<InputIterator>::value_type;
1702 return std::accumulate(first, last, static_cast<value_type>(1),
1703 std::multiplies<value_type>());
1713 template <
typename Container>
1714 typename Container::value_type
1715 prod(
const Container& c,
1716 typename std::enable_if<is_iterable<Container>::value>::type* =
nullptr) {
1717 return prod(std::begin(c), std::end(c));
1732 template <
typename Derived>
1733 dyn_col_vect<typename Derived::Scalar>
1734 rho2pure(
const Eigen::MatrixBase<Derived>& A) {
1735 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1739 if (!internal::check_nonzero_size(rA))
1740 throw exception::ZeroSize(
"qpp::rho2pure()");
1742 if (!internal::check_square_mat(rA))
1743 throw exception::MatrixNotSquare(
"qpp::rho2pure()");
1746 dyn_col_vect<double> tmp_evals = hevals(rA);
1747 cmat tmp_evects = hevects(rA);
1748 dyn_col_vect<typename Derived::Scalar> result =
1749 dyn_col_vect<typename Derived::Scalar>::Zero(rA.rows());
1752 for (idx k = 0; k < static_cast<idx>(rA.rows()); ++k) {
1753 if (std::abs(tmp_evals(k)) > 0) {
1754 result = tmp_evects.col(k);
1770 inline std::vector<idx> complement(std::vector<idx> subsys, idx n) {
1773 if (n < subsys.size())
1774 throw exception::OutOfRange(
"qpp::complement()");
1775 for (idx i = 0; i < subsys.size(); ++i)
1777 throw exception::SubsysMismatchDims(
"qpp::complement()");
1780 std::vector<idx> all(n);
1781 std::vector<idx> subsys_bar(n - subsys.size());
1783 std::iota(std::begin(all), std::end(all), 0);
1784 std::sort(std::begin(subsys), std::end(subsys));
1785 std::set_difference(std::begin(all), std::end(all), std::begin(subsys),
1786 std::end(subsys), std::begin(subsys_bar));
1801 template <
typename Derived>
1802 std::vector<double> rho2bloch(
const Eigen::MatrixBase<Derived>& A) {
1803 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1808 if (!internal::check_qubit_matrix(rA))
1809 throw exception::NotQubitMatrix(
"qpp::rho2bloch()");
1812 std::vector<double> result(3);
1813 cmat X(2, 2), Y(2, 2), Z(2, 2);
1815 Y << 0, -1_i, 1_i, 0;
1817 result[0] = std::real(trace(rA * X));
1818 result[1] = std::real(trace(rA * Y));
1819 result[2] = std::real(trace(rA * Z));
1832 inline cmat bloch2rho(
const std::vector<double>& r) {
1837 throw exception::CustomException(
"qpp::bloch2rho",
1838 "r is not a 3-dimensional vector!");
1841 cmat X(2, 2), Y(2, 2), Z(2, 2), Id2(2, 2);
1843 Y << 0, -1_i, 1_i, 0;
1847 return (Id2 + r[0] * X + r[1] * Y + r[2] * Z) / 2.;
1850 inline namespace literals {
1861 template <
char... Bits>
1862 ket
operator"" _ket() {
1863 constexpr idx n =
sizeof...(Bits);
1864 constexpr
char bits[n + 1] = {Bits...,
'\0'};
1865 qpp::ket q = qpp::ket::Zero(static_cast<idx>(std::llround(std::pow(2, n))));
1871 for (idx i = 0; i < n; ++i) {
1872 if (bits[i] !=
'0' && bits[i] !=
'1')
1873 throw exception::OutOfRange(R
"xxx(qpp::operator "" _ket())xxx"); 1877 pos = std::stoi(bits,
nullptr, 2);
1892 template <
char... Bits>
1893 bra
operator"" _bra() {
1894 constexpr idx n =
sizeof...(Bits);
1895 constexpr
char bits[n + 1] = {Bits...,
'\0'};
1896 qpp::bra q = qpp::ket::Zero(static_cast<idx>(std::llround(std::pow(2, n))));
1902 for (idx i = 0; i < n; ++i) {
1903 if (bits[i] !=
'0' && bits[i] !=
'1')
1904 throw exception::OutOfRange(R
"xxx(qpp::operator "" _bra())xxx"); 1908 pos = std::stoi(bits,
nullptr, 2);
1925 template <
char... Bits>
1926 cmat
operator"" _prj() {
1927 constexpr idx n =
sizeof...(Bits);
1928 constexpr
char bits[n + 1] = {Bits...,
'\0'};
1933 for (idx i = 0; i < n; ++i) {
1934 if (bits[i] !=
'0' && bits[i] !=
'1')
1935 throw exception::OutOfRange(R
"xxx(qpp::operator "" _prj())xxx"); 1939 return kron(
operator""_ket<Bits...>(),
operator""_bra<Bits...>());
1943 namespace internal {
1954 void hash_combine(std::size_t& seed,
const T& v) {
1955 std::hash<T> hasher;
1956 seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
1969 template <
typename Derived>
1970 std::size_t hash_eigen(
const Eigen::MatrixBase<Derived>& A,
1971 std::size_t seed = 0) {
1972 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
1977 if (!internal::check_nonzero_size(rA))
1978 throw exception::ZeroSize(
"qpp::hash_eigen()");
1981 auto* p = rA.data();
1982 idx sizeA =
static_cast<idx
>(rA.size());
1983 for (idx i = 0; i < sizeA; ++i) {
1984 internal::hash_combine(seed, std::real(p[i]));
1985 internal::hash_combine(seed, std::imag(p[i]));
1991 namespace internal {
1997 template <
typename Derived>
1998 std::size_t operator()(
const Eigen::MatrixBase<Derived>& A)
const {
1999 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
2000 return hash_eigen(rA);
2011 template <
typename Derived>
2012 bool operator()(
const Eigen::MatrixBase<Derived>& A,
2013 const Eigen::MatrixBase<Derived>& B)
const {
2014 const dyn_mat<typename Derived::Scalar>& rA = A.derived();
2015 const dyn_mat<typename Derived::Scalar>& rB = B.derived();
2016 if (rA.rows() == rB.rows() && rA.cols() == rB.cols())
2017 return rA == rB ?
true :
false;
2029 struct EqualSameSizeStringDits {
2030 bool operator()(
const std::string& s1,
const std::string& s2)
const {
2031 std::vector<std::string> tk1, tk2;
2033 std::stringstream ss1{s1}, ss2{s2};
2037 tk1.emplace_back(w1);
2039 tk2.emplace_back(w2);
2042 auto it1 = std::begin(tk1);
2043 auto it2 = std::begin(tk2);
2044 while (it1 != std::end(tk1) && it2 != std::end(tk2)) {
2045 auto n1 = std::stoll(*it1++);
2046 auto n2 = std::stoll(*it2++);
Quantum++ main namespace.
Definition: circuits.h:35