flexiblesusy is hosted by Hepforge, IPPP Durham
FlexibleSUSY
linalg2.hpp
Go to the documentation of this file.
1// ====================================================================
2// This file is part of FlexibleSUSY.
3//
4// FlexibleSUSY is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published
6// by the Free Software Foundation, either version 3 of the License,
7// or (at your option) any later version.
8//
9// FlexibleSUSY is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with FlexibleSUSY. If not, see
16// <http://www.gnu.org/licenses/>.
17// ====================================================================
18
19#ifndef LINALG2_H
20#define LINALG2_H
21
22#include <cstdint>
23#include <limits>
24#include <cctype>
25#include <cmath>
26#include <complex>
27#include <algorithm>
28#include <Eigen/Core>
29#include <Eigen/SVD>
30#include <Eigen/Eigenvalues>
31#include <unsupported/Eigen/MatrixFunctions>
32
33namespace flexiblesusy {
34
35#define MAX_(i, j) (((i) > (j)) ? (i) : (j))
36#define MIN_(i, j) (((i) < (j)) ? (i) : (j))
37
38template<class Real, class Scalar, int M, int N>
40(const Eigen::Matrix<Scalar, M, N>& m,
41 Eigen::Array<Real, MIN_(M, N), 1>& s,
42 Eigen::Matrix<Scalar, M, M> *u,
43 Eigen::Matrix<Scalar, N, N> *vh)
44{
45 Eigen::JacobiSVD<Eigen::Matrix<Scalar, M, N> >
46 svd(m, (u ? Eigen::ComputeFullU : 0) | (vh ? Eigen::ComputeFullV : 0));
47 s = svd.singularValues();
48 if (u) { *u = svd.matrixU(); }
49 if (vh) { *vh = svd.matrixV().adjoint(); }
50}
51
52template<class Real, class Scalar, int N>
54(const Eigen::Matrix<Scalar, N, N>& m,
55 Eigen::Array<Real, N, 1>& w,
56 Eigen::Matrix<Scalar, N, N> *z)
57{
58 Eigen::SelfAdjointEigenSolver<Eigen::Matrix<Scalar,N,N> >
59 es(m, z ? Eigen::ComputeEigenvectors : Eigen::EigenvaluesOnly);
60 w = es.eigenvalues();
61 if (z) { *z = es.eigenvectors(); }
62}
63
67template<int M, int N, class Real>
68void disna(const char& JOB, const Eigen::Array<Real, MIN_(M, N), 1>& D,
69 Eigen::Array<Real, MIN_(M, N), 1>& SEP, int& INFO)
70{
71// -- LAPACK computational routine (version 3.4.0) --
72// -- LAPACK is a software package provided by Univ. of Tennessee, --
73// -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
74// November 2011
75//
76// =====================================================================
77
78// .. Parameters ..
79 const Real ZERO = 0;
80// .. Local Scalars ..
81 bool DECR, EIGEN, INCR, LEFT, RIGHT, SINGUL;
82 int I, K;
83 Real ANORM, EPS, NEWGAP, OLDGAP, SAFMIN, THRESH;
84//
85// Test the input arguments
86//
87 INFO = 0;
88 EIGEN = std::toupper(JOB) == 'E';
89 LEFT = std::toupper(JOB) == 'L';
90 RIGHT = std::toupper(JOB) == 'R';
91 SINGUL = LEFT || RIGHT;
92 if (EIGEN) {
93 K = M;
94 } else if (SINGUL) {
95 K = MIN_(M, N);
96 }
97 if (!EIGEN && !SINGUL) {
98 INFO = -1;
99 } else if (M < 0) {
100 INFO = -2;
101 } else if (K < 0) {
102 INFO = -3;
103 } else {
104 INCR = true;
105 DECR = true;
106 for (I = 0; I < K - 1; I++) {
107 if (INCR) {
108 INCR = INCR && D(I) <= D(I+1);
109 }
110 if (DECR) {
111 DECR = DECR && D(I) >= D(I+1);
112 }
113 }
114 if (SINGUL && K > 0) {
115 if (INCR) {
116 INCR = INCR && ZERO <= D(0);
117 }
118 if (DECR) {
119 DECR = DECR && D(K-1) >= ZERO;
120 }
121 }
122 if (!(INCR || DECR)) {
123 INFO = -4;
124 }
125 }
126 if (INFO != 0) {
127 // CALL XERBLA( 'DDISNA', -INFO )
128 return;
129 }
130//
131// Quick return if possible
132//
133 if (K == 0) {
134 return;
135 }
136//
137// Compute reciprocal condition numbers
138//
139 if (K == 1) {
140 SEP(0) = std::numeric_limits<Real>::max();
141 } else {
142 OLDGAP = std::fabs(D(1) - D(0));
143 SEP(0) = OLDGAP;
144 for (I = 1; I < K - 1; I++) {
145 NEWGAP = std::fabs(D(I+1) - D(I));
146 SEP(I) = std::min(OLDGAP, NEWGAP);
147 OLDGAP = NEWGAP;
148 }
149 SEP(K-1) = OLDGAP;
150 }
151 if (SINGUL) {
152 if ((LEFT && M > N) || (RIGHT && M < N)) {
153 if (INCR) {
154 SEP( 0 ) = std::min(SEP( 0 ), D( 0 ));
155 }
156 if (DECR) {
157 SEP(K-1) = std::min(SEP(K-1), D(K-1));
158 }
159 }
160 }
161//
162// Ensure that reciprocal condition numbers are not less than
163// threshold, in order to limit the size of the error bound
164//
165 // Note std::numeric_limits<double>::epsilon() == 2 * DLAMCH('E')
166 // since the former is the smallest eps such that 1.0 + eps > 1.0
167 // while DLAMCH('E') is the smallest eps such that 1.0 - eps < 1.0
169 SAFMIN = std::numeric_limits<Real>::min();
170 ANORM = std::max(std::fabs(D(0)), std::fabs(D(K-1)));
171 if (ANORM == ZERO) {
172 THRESH = EPS;
173 } else {
174 THRESH = std::max(EPS*ANORM, SAFMIN);
175 }
176 for (I = 0; I < K; I++) {
177 SEP(I) = std::max(SEP(I), THRESH);
178 }
179}
180
181
182template<class Real, class Scalar, int M, int N>
184(const Eigen::Matrix<Scalar, M, N>& m,
185 Eigen::Array<Real, MIN_(M, N), 1>& s,
186 Eigen::Matrix<Scalar, M, M> *u,
187 Eigen::Matrix<Scalar, N, N> *vh)
188{
189 svd_eigen(m, s, u, vh);
190}
191
192template<class Real, class Scalar, int M, int N>
194(const Eigen::Matrix<Scalar, M, N>& m,
195 Eigen::Array<Real, MIN_(M, N), 1>& s,
196 Eigen::Matrix<Scalar, M, M> *u = 0,
197 Eigen::Matrix<Scalar, N, N> *vh = 0,
198 Real *s_errbd = 0,
199 Eigen::Array<Real, MIN_(M, N), 1> *u_errbd = 0,
200 Eigen::Array<Real, MIN_(M, N), 1> *v_errbd = 0)
201{
202 svd_internal(m, s, u, vh);
203
204 // see http://www.netlib.org/lapack/lug/node96.html
205 if (!s_errbd) { return; }
207 *s_errbd = EPSMCH * s[0];
208
209 Eigen::Array<Real, MIN_(M, N), 1> RCOND;
210 int INFO;
211 if (u_errbd) {
212 disna<M, N>('L', s, RCOND, INFO);
213 u_errbd->fill(*s_errbd);
214 *u_errbd /= RCOND;
215 }
216 if (v_errbd) {
217 disna<M, N>('R', s, RCOND, INFO);
218 v_errbd->fill(*s_errbd);
219 *v_errbd /= RCOND;
220 }
221}
222
245template<class Real, class Scalar, int M, int N>
246void svd
247(const Eigen::Matrix<Scalar, M, N>& m,
248 Eigen::Array<Real, MIN_(M, N), 1>& s,
249 Eigen::Matrix<Scalar, M, M>& u,
250 Eigen::Matrix<Scalar, N, N>& vh)
251{
252 svd_errbd(m, s, &u, &vh);
253}
254
265template<class Real, class Scalar, int M, int N>
266void svd
267(const Eigen::Matrix<Scalar, M, N>& m,
268 Eigen::Array<Real, MIN_(M, N), 1>& s,
269 Eigen::Matrix<Scalar, M, M>& u,
270 Eigen::Matrix<Scalar, N, N>& vh,
271 Real& s_errbd)
272{
273 svd_errbd(m, s, &u, &vh, &s_errbd);
274}
275
288template<class Real, class Scalar, int M, int N>
289void svd
290(const Eigen::Matrix<Scalar, M, N>& m,
291 Eigen::Array<Real, MIN_(M, N), 1>& s,
292 Eigen::Matrix<Scalar, M, M>& u,
293 Eigen::Matrix<Scalar, N, N>& vh,
294 Real& s_errbd,
295 Eigen::Array<Real, MIN_(M, N), 1>& u_errbd,
296 Eigen::Array<Real, MIN_(M, N), 1>& v_errbd)
297{
298 svd_errbd(m, s, &u, &vh, &s_errbd, &u_errbd, &v_errbd);
299}
300
312template<class Real, class Scalar, int M, int N>
313void svd
314(const Eigen::Matrix<Scalar, M, N>& m,
315 Eigen::Array<Real, MIN_(M, N), 1>& s)
316{
317 svd_errbd(m, s);
318}
319
330template<class Real, class Scalar, int M, int N>
331void svd
332(const Eigen::Matrix<Scalar, M, N>& m,
333 Eigen::Array<Real, MIN_(M, N), 1>& s,
334 Real& s_errbd)
335{
336 svd_errbd(m, s, 0, 0, &s_errbd);
337}
338
339// Eigen::SelfAdjointEigenSolver seems to be faster than ZHEEV of ATLAS
340
341template<class Real, class Scalar, int N>
343(const Eigen::Matrix<Scalar, N, N>& m,
344 Eigen::Array<Real, N, 1>& w,
345 Eigen::Matrix<Scalar, N, N> *z)
346{
347 hermitian_eigen(m, w, z);
348}
349
350template<class Real, class Scalar, int N>
352(const Eigen::Matrix<Scalar, N, N>& m,
353 Eigen::Array<Real, N, 1>& w,
354 Eigen::Matrix<Scalar, N, N> *z = 0,
355 Real *w_errbd = 0,
356 Eigen::Array<Real, N, 1> *z_errbd = 0)
357{
359
360 // see http://www.netlib.org/lapack/lug/node89.html
361 if (!w_errbd) { return; }
363 Real mnorm = std::max(std::abs(w[0]), std::abs(w[N-1]));
364 *w_errbd = EPSMCH * mnorm;
365
366 if (!z_errbd) { return; }
367 Eigen::Array<Real, N, 1> RCONDZ;
368 int INFO;
369 disna<N, N>('E', w, RCONDZ, INFO);
370 z_errbd->fill(*w_errbd);
371 *z_errbd /= RCONDZ;
372}
373
388template<class Real, class Scalar, int N>
390(const Eigen::Matrix<Scalar, N, N>& m,
391 Eigen::Array<Real, N, 1>& w,
392 Eigen::Matrix<Scalar, N, N>& z)
393{
395}
396
408template<class Real, class Scalar, int N>
410(const Eigen::Matrix<Scalar, N, N>& m,
411 Eigen::Array<Real, N, 1>& w,
412 Eigen::Matrix<Scalar, N, N>& z,
413 Real& w_errbd)
414{
415 diagonalize_hermitian_errbd(m, w, &z, &w_errbd);
416}
417
429template<class Real, class Scalar, int N>
431(const Eigen::Matrix<Scalar, N, N>& m,
432 Eigen::Array<Real, N, 1>& w,
433 Eigen::Matrix<Scalar, N, N>& z,
434 Real& w_errbd,
435 Eigen::Array<Real, N, 1>& z_errbd)
436{
437 diagonalize_hermitian_errbd(m, w, &z, &w_errbd, &z_errbd);
438}
439
450template<class Real, class Scalar, int N>
452(const Eigen::Matrix<Scalar, N, N>& m,
453 Eigen::Array<Real, N, 1>& w)
454{
456}
457
469template<class Real, class Scalar, int N>
471(const Eigen::Matrix<Scalar, N, N>& m,
472 Eigen::Array<Real, N, 1>& w,
473 Real& w_errbd)
474{
475 diagonalize_hermitian_errbd(m, w, 0, &w_errbd);
476}
477
478template<class Real, int N>
480(const Eigen::Matrix<std::complex<Real>, N, N>& m,
481 Eigen::Array<Real, N, 1>& s,
482 Eigen::Matrix<std::complex<Real>, N, N> *u = 0,
483 Real *s_errbd = 0,
484 Eigen::Array<Real, N, 1> *u_errbd = 0)
485{
486 if (!u) {
487 svd_errbd(m, s, u, u, s_errbd, u_errbd);
488 return;
489 }
490 Eigen::Matrix<std::complex<Real>, N, N> vh;
491 svd_errbd(m, s, u, &vh, s_errbd, u_errbd);
492 // see Eq. (5) of https://doi.org/10.1016/j.amc.2014.01.170
493 Eigen::Matrix<std::complex<Real>, N, N> const Z = u->adjoint() * vh.transpose();
494 Eigen::Matrix<std::complex<Real>, N, N> Zsqrt = Z.sqrt().eval();
495 if (!Zsqrt.isUnitary()) {
496 // The formula assumes that sqrt of a unitary matrix is also unitary.
497 // This is not always true when using Eigen's build in sqrt function
498 // so we use a more generic matrixFunction in those cases.
499 // n-th derivative of sqrt(x)
500 const auto sqrtfn =
501 [](std::complex<Real> x, int n) {
502 static constexpr Real Pi = 3.141592653589793238462643383279503L;
503 return std::sqrt(Pi*x)/(2*std::tgamma(static_cast<Real>(1.5)-n)*std::pow(x, n));
504 };
505 Zsqrt = Z.matrixFunction(sqrtfn).eval();
506 if (!Zsqrt.isUnitary()) {
507 std::runtime_error("Zsqrt matrix must be unitary");
508 }
509 }
510 *u *= Zsqrt;
511}
512
526template<class Real, int N>
528(const Eigen::Matrix<std::complex<Real>, N, N>& m,
529 Eigen::Array<Real, N, 1>& s,
530 Eigen::Matrix<std::complex<Real>, N, N>& u)
531{
533}
534
546template<class Real, int N>
548(const Eigen::Matrix<std::complex<Real>, N, N>& m,
549 Eigen::Array<Real, N, 1>& s,
550 Eigen::Matrix<std::complex<Real>, N, N>& u,
551 Real& s_errbd)
552{
553 diagonalize_symmetric_errbd(m, s, &u, &s_errbd);
554}
555
567template<class Real, int N>
569(const Eigen::Matrix<std::complex<Real>, N, N>& m,
570 Eigen::Array<Real, N, 1>& s,
571 Eigen::Matrix<std::complex<Real>, N, N>& u,
572 Real& s_errbd,
573 Eigen::Array<Real, N, 1>& u_errbd)
574{
575 diagonalize_symmetric_errbd(m, s, &u, &s_errbd, &u_errbd);
576}
577
587template<class Real, int N>
589(const Eigen::Matrix<std::complex<Real>, N, N>& m,
590 Eigen::Array<Real, N, 1>& s)
591{
593}
594
606template<class Real, int N>
608(const Eigen::Matrix<std::complex<Real>, N, N>& m,
609 Eigen::Array<Real, N, 1>& s,
610 Real& s_errbd)
611{
612 diagonalize_symmetric_errbd(m, s, 0, &s_errbd);
613}
614
615template<class Real>
617 std::complex<Real> operator() (const std::complex<Real>& z) const {
618 return z.real() < 0 ? std::complex<Real>(0,1) :
619 std::complex<Real>(1,0);
620 }
621};
622
623template<class Real, int N>
625(const Eigen::Matrix<Real, N, N>& m,
626 Eigen::Array<Real, N, 1>& s,
627 Eigen::Matrix<std::complex<Real>, N, N> *u = 0,
628 Real *s_errbd = 0,
629 Eigen::Array<Real, N, 1> *u_errbd = 0)
630{
631 Eigen::Matrix<Real, N, N> z;
632 diagonalize_hermitian_errbd(m, s, u ? &z : 0, s_errbd, u_errbd);
633 // see http://forum.kde.org/viewtopic.php?f=74&t=62606
634 if (u) {
635 *u = z * s.template cast<std::complex<Real>>()
636 .unaryExpr(FlipSignOp<Real>())
637 .matrix()
638 .asDiagonal();
639 }
640 s = s.abs();
641}
642
658template<class Real, int N>
660(const Eigen::Matrix<Real, N, N>& m,
661 Eigen::Array<Real, N, 1>& s,
662 Eigen::Matrix<std::complex<Real>, N, N>& u)
663{
665}
666
678template<class Real, int N>
680(const Eigen::Matrix<Real, N, N>& m,
681 Eigen::Array<Real, N, 1>& s,
682 Eigen::Matrix<std::complex<Real>, N, N>& u,
683 Real& s_errbd)
684{
685 diagonalize_symmetric_errbd(m, s, &u, &s_errbd);
686}
687
699template<class Real, int N>
701(const Eigen::Matrix<Real, N, N>& m,
702 Eigen::Array<Real, N, 1>& s,
703 Eigen::Matrix<std::complex<Real>, N, N>& u,
704 Real& s_errbd,
705 Eigen::Array<Real, N, 1>& u_errbd)
706{
707 diagonalize_symmetric_errbd(m, s, &u, &s_errbd, &u_errbd);
708}
709
722template<class Real, int N>
724(const Eigen::Matrix<Real, N, N>& m,
725 Eigen::Array<Real, N, 1>& s)
726{
728}
729
741template<class Real, int N>
743(const Eigen::Matrix<Real, N, N>& m,
744 Eigen::Array<Real, N, 1>& s,
745 Real& s_errbd)
746{
747 diagonalize_symmetric_errbd(m, s, 0, &s_errbd);
748}
749
750template<class Real, class Scalar, int M, int N>
752(const Eigen::Matrix<Scalar, M, N>& m,
753 Eigen::Array<Real, MIN_(M, N), 1>& s,
754 Eigen::Matrix<Scalar, M, M> *u = 0,
755 Eigen::Matrix<Scalar, N, N> *vh = 0,
756 Real *s_errbd = 0,
757 Eigen::Array<Real, MIN_(M, N), 1> *u_errbd = 0,
758 Eigen::Array<Real, MIN_(M, N), 1> *v_errbd = 0)
759{
760 svd_errbd(m, s, u, vh, s_errbd, u_errbd, v_errbd);
761 s.reverseInPlace();
762 if (u) {
763 Eigen::PermutationMatrix<M> p;
764 p.setIdentity();
765 p.indices().template segment<MIN_(M, N)>(0).reverseInPlace();
766 *u *= p;
767 }
768 if (vh) {
769 Eigen::PermutationMatrix<N> p;
770 p.setIdentity();
771 p.indices().template segment<MIN_(M, N)>(0).reverseInPlace();
772 vh->transpose() *= p;
773 }
774 if (u_errbd) { u_errbd->reverseInPlace(); }
775 if (v_errbd) { v_errbd->reverseInPlace(); }
776}
777
800template<class Real, class Scalar, int M, int N>
802(const Eigen::Matrix<Scalar, M, N>& m,
803 Eigen::Array<Real, MIN_(M, N), 1>& s,
804 Eigen::Matrix<Scalar, M, M>& u,
805 Eigen::Matrix<Scalar, N, N>& vh)
806{
807 reorder_svd_errbd(m, s, &u, &vh);
808}
809
821template<class Real, class Scalar, int M, int N>
823(const Eigen::Matrix<Scalar, M, N>& m,
824 Eigen::Array<Real, MIN_(M, N), 1>& s,
825 Eigen::Matrix<Scalar, M, M>& u,
826 Eigen::Matrix<Scalar, N, N>& vh,
827 Real& s_errbd)
828{
829 reorder_svd_errbd(m, s, &u, &vh, &s_errbd);
830}
831
844template<class Real, class Scalar, int M, int N>
846(const Eigen::Matrix<Scalar, M, N>& m,
847 Eigen::Array<Real, MIN_(M, N), 1>& s,
848 Eigen::Matrix<Scalar, M, M>& u,
849 Eigen::Matrix<Scalar, N, N>& vh,
850 Real& s_errbd,
851 Eigen::Array<Real, MIN_(M, N), 1>& u_errbd,
852 Eigen::Array<Real, MIN_(M, N), 1>& v_errbd)
853{
854 reorder_svd_errbd(m, s, &u, &vh, &s_errbd, &u_errbd, &v_errbd);
855}
856
868template<class Real, class Scalar, int M, int N>
870(const Eigen::Matrix<Scalar, M, N>& m,
871 Eigen::Array<Real, MIN_(M, N), 1>& s)
872{
873 reorder_svd_errbd(m, s);
874}
875
887template<class Real, class Scalar, int M, int N>
889(const Eigen::Matrix<Scalar, M, N>& m,
890 Eigen::Array<Real, MIN_(M, N), 1>& s,
891 Real& s_errbd)
892{
893 reorder_svd_errbd(m, s, 0, 0, &s_errbd);
894}
895
896template<class Real, int N>
898(const Eigen::Matrix<std::complex<Real>, N, N>& m,
899 Eigen::Array<Real, N, 1>& s,
900 Eigen::Matrix<std::complex<Real>, N, N> *u = 0,
901 Real *s_errbd = 0,
902 Eigen::Array<Real, N, 1> *u_errbd = 0)
903{
904 diagonalize_symmetric_errbd(m, s, u, s_errbd, u_errbd);
905 s.reverseInPlace();
906 if (u) { *u = u->rowwise().reverse().eval(); }
907 if (u_errbd) { u_errbd->reverseInPlace(); }
908}
909
910template<class Real, int N>
912(const Eigen::Matrix<Real, N, N>& m,
913 Eigen::Array<Real, N, 1>& s,
914 Eigen::Matrix<std::complex<Real>, N, N> *u = 0,
915 Real *s_errbd = 0,
916 Eigen::Array<Real, N, 1> *u_errbd = 0)
917{
918 diagonalize_symmetric_errbd(m, s, u, s_errbd, u_errbd);
919 Eigen::PermutationMatrix<N> p;
920 p.setIdentity();
921 std::sort(p.indices().data(), p.indices().data() + p.indices().size(),
922 [&s] (int i, int j) { return s[i] < s[j]; });
923#if EIGEN_VERSION_AT_LEAST(3,1,4)
924 s.matrix().transpose() *= p;
925 if (u_errbd) { u_errbd->matrix().transpose() *= p; }
926#else
927 Eigen::Map<Eigen::Matrix<Real, N, 1> >(s.data()).transpose() *= p;
928 if (u_errbd) {
929 Eigen::Map<Eigen::Matrix<Real, N, 1>>(u_errbd->data()).transpose() *= p;
930 }
931#endif
932 if (u) { *u *= p; }
933}
934
949template<class Real, class Scalar, int N>
951(const Eigen::Matrix<Scalar, N, N>& m,
952 Eigen::Array<Real, N, 1>& s,
953 Eigen::Matrix<std::complex<Real>, N, N>& u)
954{
956}
957
969template<class Real, class Scalar, int N>
971(const Eigen::Matrix<Scalar, N, N>& m,
972 Eigen::Array<Real, N, 1>& s,
973 Eigen::Matrix<std::complex<Real>, N, N>& u,
974 Real& s_errbd)
975{
976 reorder_diagonalize_symmetric_errbd(m, s, &u, &s_errbd);
977}
978
990template<class Real, class Scalar, int N>
992(const Eigen::Matrix<Scalar, N, N>& m,
993 Eigen::Array<Real, N, 1>& s,
994 Eigen::Matrix<std::complex<Real>, N, N>& u,
995 Real& s_errbd,
996 Eigen::Array<Real, N, 1>& u_errbd)
997{
998 reorder_diagonalize_symmetric_errbd(m, s, &u, &s_errbd, &u_errbd);
999}
1000
1011template<class Real, class Scalar, int N>
1013(const Eigen::Matrix<Scalar, N, N>& m,
1014 Eigen::Array<Real, N, 1>& s)
1015{
1017}
1018
1030template<class Real, class Scalar, int N>
1032(const Eigen::Matrix<Scalar, N, N>& m,
1033 Eigen::Array<Real, N, 1>& s,
1034 Real& s_errbd)
1035{
1036 reorder_diagonalize_symmetric_errbd(m, s, 0, &s_errbd);
1037}
1038
1039template<class Real, class Scalar, int M, int N>
1041(const Eigen::Matrix<Scalar, M, N>& m,
1042 Eigen::Array<Real, MIN_(M, N), 1>& s,
1043 Eigen::Matrix<Scalar, M, M> *u = 0,
1044 Eigen::Matrix<Scalar, N, N> *v = 0,
1045 Real *s_errbd = 0,
1046 Eigen::Array<Real, MIN_(M, N), 1> *u_errbd = 0,
1047 Eigen::Array<Real, MIN_(M, N), 1> *v_errbd = 0)
1048{
1049 reorder_svd_errbd(m, s, u, v, s_errbd, u_errbd, v_errbd);
1050 if (u) { u->transposeInPlace(); }
1051}
1052
1076template<class Real, class Scalar, int M, int N>
1078(const Eigen::Matrix<Scalar, M, N>& m,
1079 Eigen::Array<Real, MIN_(M, N), 1>& s,
1080 Eigen::Matrix<Scalar, M, M>& u,
1081 Eigen::Matrix<Scalar, N, N>& v)
1082{
1083 fs_svd_errbd(m, s, &u, &v);
1084}
1085
1097template<class Real, class Scalar, int M, int N>
1099(const Eigen::Matrix<Scalar, M, N>& m,
1100 Eigen::Array<Real, MIN_(M, N), 1>& s,
1101 Eigen::Matrix<Scalar, M, M>& u,
1102 Eigen::Matrix<Scalar, N, N>& v,
1103 Real& s_errbd)
1104{
1105 fs_svd_errbd(m, s, &u, &v, &s_errbd);
1106}
1107
1120template<class Real, class Scalar, int M, int N>
1122(const Eigen::Matrix<Scalar, M, N>& m,
1123 Eigen::Array<Real, MIN_(M, N), 1>& s,
1124 Eigen::Matrix<Scalar, M, M>& u,
1125 Eigen::Matrix<Scalar, N, N>& v,
1126 Real& s_errbd,
1127 Eigen::Array<Real, MIN_(M, N), 1>& u_errbd,
1128 Eigen::Array<Real, MIN_(M, N), 1>& v_errbd)
1129{
1130 fs_svd_errbd(m, s, &u, &v, &s_errbd, &u_errbd, &v_errbd);
1131}
1132
1144template<class Real, class Scalar, int M, int N>
1146(const Eigen::Matrix<Scalar, M, N>& m,
1147 Eigen::Array<Real, MIN_(M, N), 1>& s)
1148{
1149 fs_svd_errbd(m, s);
1150}
1151
1162template<class Real, class Scalar, int M, int N>
1164(const Eigen::Matrix<Scalar, M, N>& m,
1165 Eigen::Array<Real, MIN_(M, N), 1>& s,
1166 Real& s_errbd)
1167{
1168 fs_svd_errbd(m, s, 0, 0, &s_errbd);
1169}
1170
1197template<class Real, int M, int N>
1199(const Eigen::Matrix<Real, M, N>& m,
1200 Eigen::Array<Real, MIN_(M, N), 1>& s,
1201 Eigen::Matrix<std::complex<Real>, M, M>& u,
1202 Eigen::Matrix<std::complex<Real>, N, N>& v)
1203{
1204 fs_svd(m.template cast<std::complex<Real> >().eval(), s, u, v);
1205}
1206
1218template<class Real, int M, int N>
1220(const Eigen::Matrix<Real, M, N>& m,
1221 Eigen::Array<Real, MIN_(M, N), 1>& s,
1222 Eigen::Matrix<std::complex<Real>, M, M>& u,
1223 Eigen::Matrix<std::complex<Real>, N, N>& v,
1224 Real& s_errbd)
1225{
1226 fs_svd(m.template cast<std::complex<Real> >().eval(), s, u, v, s_errbd);
1227}
1228
1241template<class Real, int M, int N>
1243(const Eigen::Matrix<Real, M, N>& m,
1244 Eigen::Array<Real, MIN_(M, N), 1>& s,
1245 Eigen::Matrix<std::complex<Real>, M, M>& u,
1246 Eigen::Matrix<std::complex<Real>, N, N>& v,
1247 Real& s_errbd,
1248 Eigen::Array<Real, MIN_(M, N), 1>& u_errbd,
1249 Eigen::Array<Real, MIN_(M, N), 1>& v_errbd)
1250{
1251 fs_svd(m.template cast<std::complex<Real> >().eval(), s, u, v,
1252 s_errbd, u_errbd, v_errbd);
1253}
1254
1255template<class Real, class Scalar, int N>
1257(const Eigen::Matrix<Scalar, N, N>& m,
1258 Eigen::Array<Real, N, 1>& s,
1259 Eigen::Matrix<std::complex<Real>, N, N> *u = 0,
1260 Real *s_errbd = 0,
1261 Eigen::Array<Real, N, 1> *u_errbd = 0)
1262{
1263 reorder_diagonalize_symmetric_errbd(m, s, u, s_errbd, u_errbd);
1264 if (u) { u->transposeInPlace(); }
1265}
1266
1282template<class Real, class Scalar, int N>
1284(const Eigen::Matrix<Scalar, N, N>& m,
1285 Eigen::Array<Real, N, 1>& s,
1286 Eigen::Matrix<std::complex<Real>, N, N>& u)
1287{
1289}
1290
1302template<class Real, class Scalar, int N>
1304(const Eigen::Matrix<Scalar, N, N>& m,
1305 Eigen::Array<Real, N, 1>& s,
1306 Eigen::Matrix<std::complex<Real>, N, N>& u,
1307 Real& s_errbd)
1308{
1309 fs_diagonalize_symmetric_errbd(m, s, &u, &s_errbd);
1310}
1311
1323template<class Real, class Scalar, int N>
1325(const Eigen::Matrix<Scalar, N, N>& m,
1326 Eigen::Array<Real, N, 1>& s,
1327 Eigen::Matrix<std::complex<Real>, N, N>& u,
1328 Real& s_errbd,
1329 Eigen::Array<Real, N, 1>& u_errbd)
1330{
1331 fs_diagonalize_symmetric_errbd(m, s, &u, &s_errbd, &u_errbd);
1332}
1333
1344template<class Real, class Scalar, int N>
1346(const Eigen::Matrix<Scalar, N, N>& m,
1347 Eigen::Array<Real, N, 1>& s)
1348{
1350}
1351
1363template<class Real, class Scalar, int N>
1365(const Eigen::Matrix<Scalar, N, N>& m,
1366 Eigen::Array<Real, N, 1>& s,
1367 Real& s_errbd)
1368{
1369 fs_diagonalize_symmetric_errbd(m, s, 0, &s_errbd);
1370}
1371
1372template<class Real, class Scalar, int N>
1374(const Eigen::Matrix<Scalar, N, N>& m,
1375 Eigen::Array<Real, N, 1>& w,
1376 Eigen::Matrix<Scalar, N, N> *z = 0,
1377 Real *w_errbd = 0,
1378 Eigen::Array<Real, N, 1> *z_errbd = 0)
1379{
1380 diagonalize_hermitian_errbd(m, w, z, w_errbd, z_errbd);
1381 Eigen::PermutationMatrix<N> p;
1382 p.setIdentity();
1383 std::sort(p.indices().data(), p.indices().data() + p.indices().size(),
1384 [&w] (int i, int j) { return std::abs(w[i]) < std::abs(w[j]); });
1385#if EIGEN_VERSION_AT_LEAST(3,1,4)
1386 w.matrix().transpose() *= p;
1387 if (z_errbd) { z_errbd->matrix().transpose() *= p; }
1388#else
1389 Eigen::Map<Eigen::Matrix<Real, N, 1> >(w.data()).transpose() *= p;
1390 if (z_errbd) {
1391 Eigen::Map<Eigen::Matrix<Real, N, 1>>(z_errbd->data()).transpose() *= p;
1392 }
1393#endif
1394 if (z) { *z = (*z * p).adjoint().eval(); }
1395}
1396
1411template<class Real, class Scalar, int N>
1413(const Eigen::Matrix<Scalar, N, N>& m,
1414 Eigen::Array<Real, N, 1>& w,
1415 Eigen::Matrix<Scalar, N, N>& z)
1416{
1418}
1419
1431template<class Real, class Scalar, int N>
1433(const Eigen::Matrix<Scalar, N, N>& m,
1434 Eigen::Array<Real, N, 1>& w,
1435 Eigen::Matrix<Scalar, N, N>& z,
1436 Real& w_errbd)
1437{
1438 fs_diagonalize_hermitian_errbd(m, w, &z, &w_errbd);
1439}
1440
1452template<class Real, class Scalar, int N>
1454(const Eigen::Matrix<Scalar, N, N>& m,
1455 Eigen::Array<Real, N, 1>& w,
1456 Eigen::Matrix<Scalar, N, N>& z,
1457 Real& w_errbd,
1458 Eigen::Array<Real, N, 1>& z_errbd)
1459{
1460 fs_diagonalize_hermitian_errbd(m, w, &z, &w_errbd, &z_errbd);
1461}
1462
1473template<class Real, class Scalar, int N>
1475(const Eigen::Matrix<Scalar, N, N>& m,
1476 Eigen::Array<Real, N, 1>& w)
1477{
1479}
1480
1492template<class Real, class Scalar, int N>
1494(const Eigen::Matrix<Scalar, N, N>& m,
1495 Eigen::Array<Real, N, 1>& w,
1496 Real& w_errbd)
1497{
1498 fs_diagonalize_hermitian_errbd(m, w, 0, &w_errbd);
1499}
1500
1508template <typename T>
1509double calculate_singlet_mass(T value) noexcept
1510{
1511 return std::abs(value);
1512}
1513
1527template <typename T>
1528double calculate_majorana_singlet_mass(T value, std::complex<double>& phase)
1529{
1530 phase = std::polar(1., 0.5 * std::arg(std::complex<double>(value)));
1531 return std::abs(value);
1532}
1533
1547template <typename T>
1548double calculate_dirac_singlet_mass(T value, std::complex<double>& phase)
1549{
1550 phase = std::polar(1., std::arg(std::complex<double>(value)));
1551 return std::abs(value);
1552}
1553
1554} // namespace flexiblesusy
1555
1556#endif // LINALG2_H
#define M(i)
Definition: defs.h:629
#define MIN_(i, j)
Definition: linalg2.hpp:36
#define INFO(msg)
Definition: logger.hpp:61
std::complex< T > phase(const std::complex< T > &z) noexcept
Definition: ckm.cpp:236
void() D(dd)) coeff_t &arr
void reorder_diagonalize_symmetric(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &s, Eigen::Matrix< std::complex< Real >, N, N > &u)
Definition: linalg2.hpp:951
const Real epsilon
Definition: mathdefs.hpp:18
double calculate_majorana_singlet_mass(T value, std::complex< double > &phase)
Definition: linalg2.hpp:1528
void reorder_diagonalize_symmetric_errbd(const Eigen::Matrix< std::complex< Real >, N, N > &m, Eigen::Array< Real, N, 1 > &s, Eigen::Matrix< std::complex< Real >, N, N > *u=0, Real *s_errbd=0, Eigen::Array< Real, N, 1 > *u_errbd=0)
Definition: linalg2.hpp:898
void diagonalize_hermitian_internal(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &w, Eigen::Matrix< Scalar, N, N > *z)
Definition: linalg2.hpp:343
void reorder_svd(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > &u, Eigen::Matrix< Scalar, N, N > &vh)
Definition: linalg2.hpp:802
void diagonalize_hermitian_errbd(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &w, Eigen::Matrix< Scalar, N, N > *z=0, Real *w_errbd=0, Eigen::Array< Real, N, 1 > *z_errbd=0)
Definition: linalg2.hpp:352
void fs_svd(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > &u, Eigen::Matrix< Scalar, N, N > &v)
Definition: linalg2.hpp:1078
double Real
Definition: mathdefs.hpp:12
void svd_eigen(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > *u, Eigen::Matrix< Scalar, N, N > *vh)
Definition: linalg2.hpp:40
void fs_diagonalize_symmetric_errbd(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &s, Eigen::Matrix< std::complex< Real >, N, N > *u=0, Real *s_errbd=0, Eigen::Array< Real, N, 1 > *u_errbd=0)
Definition: linalg2.hpp:1257
void disna(const char &JOB, const Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &D, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &SEP, int &INFO)
Definition: linalg2.hpp:68
void svd_internal(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > *u, Eigen::Matrix< Scalar, N, N > *vh)
Definition: linalg2.hpp:184
void fs_diagonalize_hermitian(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &w, Eigen::Matrix< Scalar, N, N > &z)
Definition: linalg2.hpp:1413
void diagonalize_hermitian(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &w, Eigen::Matrix< Scalar, N, N > &z)
Definition: linalg2.hpp:390
constexpr T arg(const Complex< T > &z) noexcept
Definition: complex.hpp:42
void diagonalize_symmetric_errbd(const Eigen::Matrix< std::complex< Real >, N, N > &m, Eigen::Array< Real, N, 1 > &s, Eigen::Matrix< std::complex< Real >, N, N > *u=0, Real *s_errbd=0, Eigen::Array< Real, N, 1 > *u_errbd=0)
Definition: linalg2.hpp:480
double calculate_dirac_singlet_mass(T value, std::complex< double > &phase)
Definition: linalg2.hpp:1548
double calculate_singlet_mass(T value) noexcept
Definition: linalg2.hpp:1509
void svd_errbd(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > *u=0, Eigen::Matrix< Scalar, N, N > *vh=0, Real *s_errbd=0, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > *u_errbd=0, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > *v_errbd=0)
Definition: linalg2.hpp:194
void fs_svd_errbd(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > *u=0, Eigen::Matrix< Scalar, N, N > *v=0, Real *s_errbd=0, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > *u_errbd=0, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > *v_errbd=0)
Definition: linalg2.hpp:1041
void fs_diagonalize_hermitian_errbd(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &w, Eigen::Matrix< Scalar, N, N > *z=0, Real *w_errbd=0, Eigen::Array< Real, N, 1 > *z_errbd=0)
Definition: linalg2.hpp:1374
void svd(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > &u, Eigen::Matrix< Scalar, N, N > &vh)
Definition: linalg2.hpp:247
void reorder_svd_errbd(const Eigen::Matrix< Scalar, M, N > &m, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > &s, Eigen::Matrix< Scalar, M, M > *u=0, Eigen::Matrix< Scalar, N, N > *vh=0, Real *s_errbd=0, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > *u_errbd=0, Eigen::Array< Real,(((M)<(N)) ?(M) :(N)), 1 > *v_errbd=0)
Definition: linalg2.hpp:752
static constexpr double Pi
Definition: wrappers.hpp:44
void diagonalize_symmetric(const Eigen::Matrix< std::complex< Real >, N, N > &m, Eigen::Array< Real, N, 1 > &s, Eigen::Matrix< std::complex< Real >, N, N > &u)
Definition: linalg2.hpp:528
void fs_diagonalize_symmetric(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &s, Eigen::Matrix< std::complex< Real >, N, N > &u)
Definition: linalg2.hpp:1284
void hermitian_eigen(const Eigen::Matrix< Scalar, N, N > &m, Eigen::Array< Real, N, 1 > &w, Eigen::Matrix< Scalar, N, N > *z)
Definition: linalg2.hpp:54
std::complex< Real > operator()(const std::complex< Real > &z) const
Definition: linalg2.hpp:617