eigen.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /* taken from i.pca */
  2. #include <stdlib.h>
  3. #include <grass/gmath.h>
  4. #include <grass/gis.h>
  5. static int egcmp(const void *pa, const void *pb);
  6. /*!
  7. * \fn int eigen (double **M, double **Vectors, double *lambda, int n)
  8. *
  9. * \brief Computes eigenvalues (and eigen vectors if desired) for
  10. * symmetric matices.
  11. *
  12. * Computes eigenvalues (and eigen vectors if desired) for symmetric matices.
  13. *
  14. * \param M Input matrix
  15. * \param Vectors eigen output vector matrix
  16. * \param lambda Output eigenvalues
  17. * \param n Input matrix dimension
  18. * \return int
  19. */
  20. int eigen(double **M, /* Input matrix */
  21. double **Vectors, /* eigen vector matrix -output */
  22. double *lambda, /* Output eigenvalues */
  23. int n /* Input matrix dimension */
  24. )
  25. {
  26. int i, j;
  27. double **a, *e;
  28. a = G_alloc_matrix(n, n);
  29. e = G_alloc_vector(n);
  30. for (i = 0; i < n; i++)
  31. for (j = 0; j < n; j++)
  32. a[i][j] = M[i][j];
  33. G_tred2(a, n, lambda, e);
  34. G_tqli(lambda, e, n, a);
  35. /* Returns eigenvectors */
  36. for (i = 0; i < n; i++)
  37. for (j = 0; j < n; j++)
  38. Vectors[i][j] = a[i][j];
  39. G_free_matrix(a);
  40. G_free_vector(e);
  41. return 0;
  42. }
  43. /*!
  44. * \fn int egvorder2 (double *d, double **z, long bands)
  45. *
  46. * \brief
  47. *
  48. * Returns 0.
  49. *
  50. * \param d
  51. * \param z
  52. * \param bands
  53. * \return int
  54. */
  55. int egvorder2(double *d, double **z, long bands)
  56. {
  57. double *buff;
  58. double **tmp;
  59. int i, j;
  60. /* allocate temporary matrix */
  61. buff = (double *)G_malloc(bands * (bands + 1) * sizeof(double));
  62. tmp = (double **)G_malloc(bands * sizeof(double *));
  63. for (i = 0; i < bands; i++)
  64. tmp[i] = &buff[i * (bands + 1)];
  65. /* concatenate (vertically) z and d into tmp */
  66. for (i = 0; i < bands; i++) {
  67. for (j = 0; j < bands; j++)
  68. tmp[i][j + 1] = z[j][i];
  69. tmp[i][0] = d[i];
  70. }
  71. /* sort the combined matrix */
  72. qsort(tmp, bands, sizeof(double *), egcmp);
  73. /* split tmp into z and d */
  74. for (i = 0; i < bands; i++) {
  75. for (j = 0; j < bands; j++)
  76. z[j][i] = tmp[i][j + 1];
  77. d[i] = tmp[i][0];
  78. }
  79. /* free temporary matrix */
  80. G_free(tmp);
  81. G_free(buff);
  82. return 0;
  83. }
  84. /*!
  85. * \fn int transpose2 (double **eigmat, long bands)
  86. *
  87. * \brief
  88. *
  89. * Returns 0.
  90. *
  91. * \param eigmat
  92. * \param bands
  93. * \return int
  94. */
  95. int transpose2(double **eigmat, long bands)
  96. {
  97. int i, j;
  98. for (i = 0; i < bands; i++)
  99. for (j = 0; j < i; j++) {
  100. double tmp = eigmat[i][j];
  101. eigmat[i][j] = eigmat[j][i];
  102. eigmat[j][i] = tmp;
  103. }
  104. return 0;
  105. }
  106. static int egcmp(const void *pa, const void *pb)
  107. {
  108. const double *a = *(const double *const *)pa;
  109. const double *b = *(const double *const *)pb;
  110. if (*a > *b)
  111. return -1;
  112. if (*a < *b)
  113. return 1;
  114. return 0;
  115. }