EigValuesTRLAN.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #include "EigValuesTRLAN.h"
  2. #include <iostream>
  3. #include <assert.h>
  4. using namespace NICE;
  5. using namespace std;
  6. #ifdef NICE_USELIB_TRLAN
  7. /** some hacks to use the C functions in the TRLAN library */
  8. static const GenericMatrix* mat = NULL;
  9. /** generic vector matrix multiplication */
  10. static void op ( int* nrow, int* ncol, double* xin, int* ldx, double* xout, int* ldy )
  11. {
  12. NICE::Vector xin_v ( xin, *ldy, NICE::VectorBase::external );
  13. NICE::Vector xout_v ( xout, *ldy, NICE::VectorBase::external );
  14. mat->multiply ( xout_v, xin_v );
  15. }
  16. /** imports from the TRLAN library */
  17. typedef void ( *OpFunc ) ( int* nrow, int* ncol, double* xin, int* ldx, double* xout, int* ldy );
  18. extern "C" void trlan77_ ( OpFunc op, int ipar[32], int* nrowl, int* mev, double* eval,
  19. double* evec, int* nrow2, double* wrk, int* lwrk );
  20. #endif
  21. /** constructor, initialize some settings */
  22. EigValuesTRLAN::EigValuesTRLAN ( int magnitude,
  23. int restarting_scheme,
  24. double tolerance,
  25. int max_mult,
  26. int mult_flops )
  27. {
  28. this->magnitude = magnitude;
  29. this->restarting_scheme = restarting_scheme;
  30. this->tolerance = tolerance;
  31. this->max_mult = max_mult;
  32. this->mult_flops = mult_flops;
  33. this->verbose = false;
  34. }
  35. /** get some eigenvalues */
  36. void EigValuesTRLAN::getEigenvalues ( const GenericMatrix &data, NICE::Vector & eigenvalues, NICE::Matrix & eigenvectors, uint k )
  37. {
  38. #ifndef NICE_USELIB_TRLAN
  39. fthrow ( Exception, "EigValuesTRLAN::getEigenvalues: this functions needs the TRLAN library" );
  40. #else
  41. if ( verbose )
  42. fprintf ( stderr, "Starting eigenvalue computation with Lanczos Iteration ...\n" );
  43. assert ( data.rows() == data.cols() );
  44. if ( data.rows() != data.cols() ) {
  45. fthrow ( Exception, "EigValuesTRLAN::getEigenvalues: the input matrix is not quadratic\n" );
  46. }
  47. /** set the global matrix */
  48. mat = &data;
  49. int mat_size = ( int ) data.rows();
  50. if ( max_mult <= 0 ) max_mult = 10 * mat_size;
  51. if ( mult_flops <= 0 ) mult_flops = 10 * mat_size;
  52. /** intialize TRLAN stuff */
  53. int computed_eigenpairs = k;
  54. int ipar[32] = {0, magnitude, computed_eigenpairs, 0, 0, restarting_scheme, max_mult, 0, 1, 99, -1, 98, mult_flops};
  55. double* evalbuff = new double[k];
  56. memset ( evalbuff, 0, k*sizeof ( double ) );
  57. double* evecbuff = new double[k*mat_size];
  58. memset ( evecbuff, 1, k*mat_size*sizeof ( double ) );
  59. int ritz_size = ( computed_eigenpairs < 3 ? 2 * computed_eigenpairs : computed_eigenpairs + 6 );
  60. int workspace_size = ritz_size * ( ritz_size + 10 );
  61. double* workspace = new double[workspace_size];
  62. workspace[0] = tolerance;
  63. if ( verbose )
  64. cerr << "Initialization ready ... Starting TRLAN" << endl;
  65. // call lanczos iteration of trlan
  66. int kint = k;
  67. trlan77_ ( op, ipar, &mat_size, &kint, evalbuff, evecbuff, &mat_size, workspace, &workspace_size );
  68. if ( ipar[0] != 0 )
  69. {
  70. cerr << "EigValuesTRLAN: Error occured by calling TRLAN Eigenvalue Computation." << endl;
  71. cerr << "EigValuesTRLAN: " << ipar[3] << " converged eigenvectors" << endl;
  72. }
  73. if ( verbose )
  74. cerr << "TRLAN ready" << endl;
  75. // copy eigenvectors in evecbuff to vector
  76. eigenvectors.resize ( mat_size, k );
  77. eigenvalues.resize ( k );
  78. if ( verbose )
  79. cerr << "Store results" << endl;
  80. /** write back all eigenvalues and eigenvectors */
  81. if ( magnitude < 0 )
  82. {
  83. for ( uint i = 0;i < k;i++ )
  84. for ( uint j = 0;j < ( uint ) mat_size;j++ )
  85. eigenvectors ( j, i ) = evecbuff[i*mat_size+j];
  86. for ( uint i = 0;i < k;i++ )
  87. eigenvalues[i] = evalbuff[i];
  88. }
  89. else
  90. {
  91. for ( uint i = 0;i < k;i++ )
  92. for ( uint j = 0;j < ( uint ) mat_size;j++ )
  93. eigenvectors ( j, k - i - 1 ) = evecbuff[i*mat_size+j];
  94. for ( uint i = 0;i < k;i++ )
  95. eigenvalues[i] = evalbuff[k-i-1];
  96. }
  97. if ( verbose )
  98. cerr << "Clean up" << endl;
  99. /** clean up memory */
  100. delete[] workspace;
  101. delete[] evalbuff;
  102. delete[] evecbuff;
  103. if ( verbose )
  104. cerr << "Clean up done" << endl;
  105. #endif
  106. }