29#ifndef math_eigenLapack_hpp
30#define math_eigenLapack_hpp
32#pragma GCC system_header
40#include "../sys/timeUtils.hpp"
44#include "../math/plot/gnuPlot.hpp"
61template <
typename eigenT1,
typename eigenT2>
85template <
typename floatT>
91 MXLAPACK_INT numeig{ 0 };
95 MXLAPACK_INT sizeISuppZ{ 0 };
96 MXLAPACK_INT sizeMinWork{ 0 };
97 MXLAPACK_INT sizeWork{ 0 };
98 MXLAPACK_INT sizeMinIWork{ 0 };
99 MXLAPACK_INT sizeIWork{ 0 };
101 MXLAPACK_INT *iSuppZ{
nullptr };
103 floatT *minWork{
nullptr };
104 floatT *work{
nullptr };
106 MXLAPACK_INT *minIWork{
nullptr };
107 MXLAPACK_INT *iWork{
nullptr };
110 Eigen::Array<floatT, Eigen::Dynamic, Eigen::Dynamic> cvd, evecsd, evalsd;
188template <
typename arrT>
206 typedef typename arrT::Scalar
calcT;
208 MXLAPACK_INT numeig, info;
219 MXLAPACK_INT n = X.rows();
230 eigvec.resize( n, IU - IL + 1 );
233 if( UPLO !=
mem->UPLO || n !=
mem->n || RANGE !=
mem->RANGE ||
mem->numeig != numeig ||
mem->IL != IL ||
236 if(
mem->sizeISuppZ < 2 * n )
243 mem->sizeISuppZ = 2 * n;
244 mem->iSuppZ = (MXLAPACK_INT *)
malloc(
mem->sizeISuppZ *
sizeof( MXLAPACK_INT ) );
258 if(
mem->sizeMinWork < 26 * n )
262 free(
mem->minWork );
264 mem->sizeMinWork = 26 * n;
269 if(
mem->sizeMinIWork < 10 * n )
273 free(
mem->minIWork );
275 mem->sizeMinIWork = 10 * n;
276 mem->minIWork = (MXLAPACK_INT *)
malloc(
mem->sizeMinIWork *
sizeof( MXLAPACK_INT ) );
315 if(
mem->sizeWork < ( (MXLAPACK_INT)
mem->minWork[0] ) * ( 1 ) )
322 mem->sizeWork = ( (MXLAPACK_INT)
mem->minWork[0] ) * 1;
326 if(
mem->sizeIWork <
mem->minIWork[0] * 1 )
333 mem->sizeIWork =
mem->minIWork[0] * 1;
334 mem->iWork = (MXLAPACK_INT *)
malloc( (
mem->sizeIWork ) *
sizeof( MXLAPACK_INT ) );
350 mem->numeig = numeig;
396template <
typename _evCalcT =
double,
typename eigenT>
403 bool normalize =
false,
410 double *t_eigenv =
nullptr
415 typedef typename eigenT::Scalar realT;
425 if(
cv.rows() !=
cv.cols() )
427 std::cerr <<
"calcEigenVecs: Non-square covariance matrix input to calcKLModes\n";
435 MXLAPACK_INT
tNims =
cv.rows();
456 std::cerr <<
"calcEigenVecs: eigenSYEVR returned an error (info = " << info <<
")\n";
473 for( MXLAPACK_INT
i = 0;
i <
nVecs; ++
i )
480 for( MXLAPACK_INT
i = 0;
i <
nVecs; ++
i )
484 std::cerr <<
"got 0 eigenvalue (# " <<
i <<
")\n";
489 std::cerr <<
"got < 0 eigenvalue (# " <<
i <<
")\n";
492 else if( !std::isnormal(
evals(
i ) ) )
494 std::cerr <<
"got not-normal eigenvalue (# " <<
i <<
")\n";
502 for(
int r = 0; r <
evecs.rows(); ++r )
504 if( !std::isnormal(
evecs.col(
i )( r ) ) )
506 std::cerr <<
"got not-normal eigenvector entry (# " <<
i <<
"," << r <<
")\n";
538template <
typename _evCalcT =
double,
typename eigenT,
typename eigenT1>
547 double *t_eigenv =
nullptr,
549 double *t_klim =
nullptr
553 typedef typename eigenT::Scalar realT;
563 if(
cv.rows() !=
Rims.cols() )
565 std::cerr <<
"Covariance matrix - reference image size mismatch in calcKLModes\n";
571 MXLAPACK_INT
tNims =
cv.rows();
585 std::cerr <<
"calckKLModes: eigenSYEVR returned an error (info = " << info <<
")\n";
643template <
typename dataT>
645 Eigen::Array<dataT, -1, -1> &S,
646 Eigen::Array<dataT, -1, -1> &VT,
648 Eigen::Array<dataT, -1, -1> &A
652 MXLAPACK_INT
M = A.rows();
653 MXLAPACK_INT
N = A.cols();
654 MXLAPACK_INT
LDA =
M;
657 MXLAPACK_INT
LDU =
M;
659 MXLAPACK_INT
LDVT =
N;
662 MXLAPACK_INT
LWORK = -1;
664 MXLAPACK_INT *
IWORK =
new MXLAPACK_INT[8 *
M];
668 dataT>(
JOBZ,
M,
N, A.data(),
LDA, S.data(), U.data(),
LDU, VT.data(),
LDVT, &
wkOpt,
LWORK,
IWORK,
INFO );
675 dataT>(
JOBZ,
M,
N, A.data(),
LDA, S.data(), U.data(),
LDU, VT.data(),
LDVT,
WORK,
LWORK,
IWORK,
INFO );
683#define MX_PINV_NO_INTERACT 0
684#define MX_PINV_PLOT 1
686#define MX_PINV_ASK_NMODES 4
703template <
typename dataT>
707 Eigen::Array<dataT, -1, -1> &U,
708 Eigen::Array<dataT, -1, -1> &S,
709 Eigen::Array<dataT, -1, -1> &VT,
728 dataT
Smax = S.maxCoeff();
732 for( MXLAPACK_INT
i = 0;
i < S.rows(); ++
i )
734 S(
i ) = (
pow( S(
i ), 2 ) +
pow( alpha *
Smax, 2 ) ) / S(
i );
740 for( MXLAPACK_INT
i = 0;
i < S.rows(); ++
i )
742 S(
i ) = S(
i ) + -alpha *
Smax;
760 gp.
command(
"set title \"SVD Singular Values\"" );
762 gp.plot( S.data(), S.rows(),
" w lp",
"singular values" );
768 std::cout <<
"Maximum singular value: " <<
Smax <<
"\n";
769 std::cout <<
"Minimum singular value: " << S.minCoeff() <<
"\n";
770 std::cout <<
"Enter singular value threshold: ";
785 std::cout <<
"Maximum singular value: " <<
Smax <<
"\n";
786 std::cout <<
"Minimum singular value: " << S.minCoeff() <<
"\n";
787 std::cout <<
"Enter number of modes to keep: ";
799 Eigen::Array<dataT, -1, -1> sigma;
800 sigma.resize( S.rows(), S.rows() );
815 for( MXLAPACK_INT
i = 0;
i < S.rows(); ++
i )
817 if( S(
i ) >= threshold )
819 sigma(
i,
i ) = 1. / S(
i );
835 std::cerr <<
"rejecting based on modes\n";
837 for( MXLAPACK_INT
i = 0;
i < S.rows(); ++
i )
841 sigma(
i,
i ) = 1. / S(
i );
855 std::vector<dataT>
vsig( sigma.rows() );
856 for(
int rr = 0;
rr < sigma.rows(); ++
rr )
862 gp.
command(
"set title \"Inverted Singular Values\"" );
864 gp.plot(
vsig.data(),
vsig.size(),
" w lp",
"inverted singular values" );
870 std::cout <<
"Modes Rejected: " <<
nRejected <<
"\n";
871 std::cout <<
"Condition Number: " <<
condition <<
"\n";
874 PInv = ( VT.matrix().transpose() * sigma.matrix().transpose() ) *
875 U.block( 0, 0, U.rows(),
minMN ).
matrix().transpose();
895template <
typename dataT>
899 Eigen::Array<dataT, -1, -1> &U,
900 Eigen::Array<dataT, -1, -1> &S,
901 Eigen::Array<dataT, -1, -1> &VT,
903 Eigen::Array<dataT, -1, -1> &A,
920 int minMN = std::min( A.rows(), A.cols() );
927 std::cerr <<
"eigenPseudoInverse: eigenGESDD failed with info = " << info <<
"\n";
951template <
typename dataT>
956 Eigen::Array<dataT, -1, -1> &A,
973 Eigen::Array<dataT, -1, -1> S, U, VT;
An interactive c++ interface to gnuplot.
int command(const std::string &com, bool flush=true)
Send a command to gnuplot.
MXLAPACK_INT calcKLModes(eigenT &klModes, eigenT &cv, const eigenT1 &Rims, int n_modes=0, syevrMem< _evCalcT > *mem=0, double *t_eigenv=nullptr, double *t_klim=nullptr)
Calculate the K-L modes, or principle components, given a covariance matrix.
MXLAPACK_INT calcEigenVecs(eigenT &evecs, eigenT &evals, eigenT &cv, int nVecs=0, bool normalize=false, bool check=false, syevrMem< _evCalcT > *mem=0, double *t_eigenv=nullptr)
Calculate the eigenvectors and eigenvalues given a triangular matrix.
void eigenSYRK(eigenT1 &cv, const eigenT2 &ims)
Calculates the lower triangular part of the covariance matrix of ims.
int eigenPseudoInverse(Eigen::Array< dataT, -1, -1 > &PInv, dataT &condition, int &nRejected, Eigen::Array< dataT, -1, -1 > &U, Eigen::Array< dataT, -1, -1 > &S, Eigen::Array< dataT, -1, -1 > &VT, int minMN, dataT &maxCondition, dataT alpha=0, int interact=MX_PINV_NO_INTERACT)
Calculate the pseudo-inverse of a patrix given its SVD.
MXLAPACK_INT eigenSYEVR(arrT &eigvec, arrT &eigval, arrT &X, int ev0=0, int ev1=-1, char UPLO='L', syevrMem< typename arrT::Scalar > *mem=0)
Calculate select eigenvalues and eigenvectors of an Eigen Array.
MXLAPACK_INT eigenGESDD(Eigen::Array< dataT, -1, -1 > &U, Eigen::Array< dataT, -1, -1 > &S, Eigen::Array< dataT, -1, -1 > &VT, Eigen::Array< dataT, -1, -1 > &A)
Compute the SVD of an Eigen::Array using LAPACK's xgesdd.
constexpr floatT six_fifths()
Return 6/5 in the specified precision.
typeT get_curr_time()
Get the current system time in seconds.
A struct to hold the working memory for eigenSYEVR and maintain it between calls if desired.
Declares and defines templatized wrappers for the BLAS.
Declares and defines templatized wrappers for the Lapack library.