EigValuesTRLAN.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #include "EigValuesTRLAN.h"
  2. #include <iostream>
  3. #include <assert.h>
  4. #define DEBUG_TRLAN
  5. // #undef DEBUG_TRLAN
  6. using namespace OBJREC;
  7. using namespace std;
  8. static const GenericMatrix* mat = NULL;
  9. static void op(int* nrow, int* ncol, double* xin, int* ldx, double* xout, int* ldy)
  10. {
  11. NICE::Vector xin_v(xin, *ldy, NICE::VectorBase::external);
  12. NICE::Vector xout_v(xout, *ldy, NICE::VectorBase::external);
  13. mat->multiply(xout_v, xin_v);
  14. }
  15. typedef void (*OpFunc)(int* nrow, int* ncol, double* xin, int* ldx, double* xout, int* ldy);
  16. extern "C" void trlan77_(OpFunc op, int ipar[32], int* nrowl, int* mev, double* eval,
  17. double* evec, int* nrow2, double* wrk, int* lwrk);
  18. EigValuesTRLAN::EigValuesTRLAN(int magnitude,
  19. int restarting_scheme,
  20. double tolerance,
  21. int max_mult,
  22. int mult_flops)
  23. {
  24. this->magnitude = magnitude;
  25. this->restarting_scheme = restarting_scheme;
  26. this->tolerance = tolerance;
  27. this->max_mult = max_mult;
  28. this->mult_flops = mult_flops;
  29. }
  30. // refactor-nice.pl: check this substitution
  31. // old: void EigValuesTRLAN::getEigenvalues ( const GenericMatrix &data, Vector & eigenvalues, Matrix & eigenvectors, uint k )
  32. void EigValuesTRLAN::getEigenvalues(const GenericMatrix &data, NICE::Vector & eigenvalues, NICE::Matrix & eigenvectors, uint k)
  33. {
  34. #ifdef DEBUG_TRLAN
  35. fprintf(stderr, "Starting eigenvalue computation with Lanczos Iteration ...\n");
  36. #endif
  37. assert(data.rows() == data.cols());
  38. mat = &data;
  39. int mat_size = (int)data.rows();
  40. if (max_mult <= 0) max_mult = 10 * mat_size;
  41. if (mult_flops <= 0) mult_flops = 10 * mat_size;
  42. int computed_eigenpairs = k;
  43. int ipar[32] = {0, magnitude, computed_eigenpairs, 0, 0, restarting_scheme, max_mult, 0, 1, 99, -1, 98, mult_flops};
  44. double* evalbuff = new double[k];
  45. memset(evalbuff, 0, k*sizeof(double));
  46. double* evecbuff = new double[k*mat_size];
  47. memset(evecbuff, 1, k*mat_size*sizeof(double));
  48. int ritz_size = (computed_eigenpairs < 3 ? 2 * computed_eigenpairs : computed_eigenpairs + 6);
  49. int workspace_size = ritz_size * (ritz_size + 10);
  50. double* workspace = new double[workspace_size];
  51. workspace[0] = tolerance;
  52. #ifdef DEBUG_TRLAN
  53. fprintf(stderr, "Initialization ready ... Starting TRLAN\n");
  54. #endif
  55. // call lanczos iteration of trlan
  56. int kint = k;
  57. trlan77_(op, ipar, &mat_size, &kint, evalbuff, evecbuff, &mat_size, workspace, &workspace_size);
  58. if(ipar[0]!=0)
  59. {
  60. fprintf(stderr,"EigValuesTRLAN: Error occured by calling TRLAN Eigenvalue Computation.\n");
  61. fprintf(stderr,"EigValuesTRLAN: %d converged eigenvectors \n",ipar[3]);
  62. }
  63. #ifdef DEBUG_TRLAN
  64. fprintf(stderr, "TRLAN ready\n");
  65. #endif
  66. //copy eigenvectors in evecbuff to stl vector
  67. eigenvectors.resize(mat_size, k);
  68. eigenvalues.resize(k);
  69. #ifdef DEBUG_TRLAN
  70. fprintf(stderr, "Store results\n");
  71. #endif
  72. if (magnitude < 0)
  73. {
  74. for (uint i = 0;i < k;i++)
  75. for (uint j = 0;j < (uint)mat_size;j++)
  76. eigenvectors(j, i) = evecbuff[i*mat_size+j];
  77. for (uint i = 0;i < k;i++)
  78. eigenvalues[i] = evalbuff[i];
  79. }
  80. else
  81. {
  82. for (uint i = 0;i < k;i++)
  83. for (uint j = 0;j < (uint)mat_size;j++)
  84. eigenvectors(j, k - i - 1) = evecbuff[i*mat_size+j];
  85. for (uint i = 0;i < k;i++)
  86. eigenvalues[i] = evalbuff[k-i-1];
  87. }
  88. #ifdef DEBUG_TRLAN
  89. fprintf(stderr, "Clean up\n");
  90. #endif
  91. delete[] workspace;
  92. delete[] evalbuff;
  93. delete[] evecbuff;
  94. #ifdef DEBUG_TRLAN
  95. fprintf(stderr, "Clean up Done\n");
  96. #endif
  97. }