eigen.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. if (Vectors)
  37. for (i = 0; i < n; i++)
  38. for (j = 0; j < n; j++)
  39. Vectors[i][j] = a[i][j];
  40. G_free_matrix(a);
  41. G_free_vector(e);
  42. return 0;
  43. }
  44. /*!
  45. * \fn int egvorder2 (double *d, double **z, long bands)
  46. *
  47. * \brief
  48. *
  49. * Returns 0.
  50. *
  51. * \param d
  52. * \param z
  53. * \param bands
  54. * \return int
  55. */
  56. int egvorder2(double *d, double **z, long bands)
  57. {
  58. double *buff;
  59. double **tmp;
  60. int i, j;
  61. /* allocate temporary matrix */
  62. buff = (double *)G_malloc(bands * (bands + 1) * sizeof(double));
  63. tmp = (double **)G_malloc(bands * sizeof(double *));
  64. for (i = 0; i < bands; i++)
  65. tmp[i] = &buff[i * (bands + 1)];
  66. /* concatenate (vertically) z and d into tmp */
  67. for (i = 0; i < bands; i++) {
  68. for (j = 0; j < bands; j++)
  69. tmp[i][j + 1] = z[j][i];
  70. tmp[i][0] = d[i];
  71. }
  72. /* sort the combined matrix */
  73. qsort(tmp, bands, sizeof(double *), egcmp);
  74. /* split tmp into z and d */
  75. for (i = 0; i < bands; i++) {
  76. for (j = 0; j < bands; j++)
  77. z[j][i] = tmp[i][j + 1];
  78. d[i] = tmp[i][0];
  79. }
  80. /* free temporary matrix */
  81. G_free(tmp);
  82. G_free(buff);
  83. return 0;
  84. }
  85. /*!
  86. * \fn int transpose2 (double **eigmat, long bands)
  87. *
  88. * \brief
  89. *
  90. * Returns 0.
  91. *
  92. * \param eigmat
  93. * \param bands
  94. * \return int
  95. */
  96. int transpose2(double **eigmat, long bands)
  97. {
  98. int i, j;
  99. for (i = 0; i < bands; i++)
  100. for (j = 0; j < i; j++) {
  101. double tmp = eigmat[i][j];
  102. eigmat[i][j] = eigmat[j][i];
  103. eigmat[j][i] = tmp;
  104. }
  105. return 0;
  106. }
  107. static int egcmp(const void *pa, const void *pb)
  108. {
  109. const double *a = *(const double *const *)pa;
  110. const double *b = *(const double *const *)pb;
  111. if (*a > *b)
  112. return -1;
  113. if (*a < *b)
  114. return 1;
  115. return 0;
  116. }