matrix.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*************************************/
  2. /* Auteur : Rémi Synave */
  3. /* Date de création : 01/03/07 */
  4. /* Date de modification : 15/03/15 */
  5. /* Version : 0.4 */
  6. /*************************************/
  7. /***************************************************************************/
  8. /* This file is part of a2ri. */
  9. /* */
  10. /* a2ri is free software: you can redistribute it and/or modify it */
  11. /* under the terms of the GNU Lesser General Public License as published */
  12. /* by the Free Software Foundation, either version 3 of the License, or */
  13. /* (at your option) any later version. */
  14. /* */
  15. /* a2ri is distributed in the hope that it will be useful, */
  16. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  17. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  18. /* GNU Lesser General Public License for more details. */
  19. /* */
  20. /* You should have received a copy of the GNU Lesser General Public */
  21. /* License along with a2ri. */
  22. /* If not, see <http://www.gnu.org/licenses/>. */
  23. /***************************************************************************/
  24. #include "matrix.h"
  25. /********** INTERMEDIATE TYPES AND FUNCTIONS **********/
  26. /* Les fonctions intermédiaires sont préfixées de IF */
  27. /* et les types intermédiaires de IT */
  28. /********** MAIN FUNCTIONS **********/
  29. /**
  30. Calcul du déterminant d'une matrice
  31. @param m pointeur sur une matrice
  32. @return le déterminant
  33. */
  34. double
  35. matrix_determinant (
  36. const gsl_matrix * const m)
  37. {
  38. double det;
  39. int s;
  40. gsl_permutation *perm = gsl_permutation_alloc (m->size1);
  41. a2ri_erreur_critique_si (perm == NULL,
  42. "erreur allocation memoire pour perm\nmatrix_determinant");
  43. gsl_matrix *ludecomp = gsl_matrix_alloc (m->size1, m->size1);
  44. a2ri_erreur_critique_si (ludecomp == NULL,
  45. "erreur allocation memoire pour ludecomp\nmatrix_determinant");
  46. gsl_matrix_memcpy (ludecomp, m);
  47. //get the LU decomposition
  48. gsl_linalg_LU_decomp (ludecomp, perm, &s);
  49. //get the determinant
  50. det = gsl_linalg_LU_det (ludecomp, s);
  51. gsl_matrix_free (ludecomp);
  52. gsl_permutation_free (perm);
  53. return det;
  54. }
  55. /**
  56. Calcul de la norme de Frobenius
  57. @param m pointeur sur une matrice
  58. @return la norme de Frobenius
  59. */
  60. double
  61. matrix_frobenius_norm (
  62. const gsl_matrix * const m)
  63. {
  64. double somme = 0.0;
  65. for (size_t i = 0; i < m->size1; i++)
  66. for (size_t j = 0; j < m->size2; j++)
  67. somme += gsl_matrix_get (m, i, j) * gsl_matrix_get (m, i, j);
  68. somme = sqrt (somme);
  69. return somme;
  70. }
  71. /**
  72. Addition de deux matrices
  73. @param A pointeur sur la première matrice
  74. @param B pointeur sur la seconde matrice
  75. @return pointeur sur une matrice contenant l'addition A+B
  76. */
  77. gsl_matrix *
  78. matrix_add (
  79. const gsl_matrix * const A,
  80. const gsl_matrix * const B)
  81. {
  82. gsl_matrix *res;
  83. a2ri_erreur_critique_si (A->size1 != B->size1
  84. || A->size2 != B->size2,
  85. "matrice incompatible pour l'addition");
  86. res = gsl_matrix_alloc (A->size1, B->size2);
  87. a2ri_erreur_critique_si (res == NULL,
  88. "erreur allocation memoire pour res\nmatrix_add");
  89. for (size_t i = 0; i < A->size1; i++)
  90. for (size_t j = 0; j < A->size2; j++)
  91. gsl_matrix_set (res, i, j,
  92. gsl_matrix_get (A, i, j) + gsl_matrix_get (B, i, j));
  93. return res;
  94. }
  95. /**
  96. Soustraction de deux matrices
  97. @param A pointeur sur la première matrice
  98. @param B pointeur sur la seconde matrice
  99. @return pointeur sur une matrice contenant la soustraction A-B
  100. */
  101. gsl_matrix *
  102. matrix_sub (
  103. const gsl_matrix * const A,
  104. const gsl_matrix * const B)
  105. {
  106. gsl_matrix *res;
  107. a2ri_erreur_critique_si (A->size1 != B->size1
  108. || A->size2 != B->size2,
  109. "matrice incompatible pour la soustraction");
  110. res = gsl_matrix_alloc (A->size1, B->size2);
  111. a2ri_erreur_critique_si (res == NULL,
  112. "erreur allocation memoire pour res\nmatrix_sub");
  113. for (size_t i = 0; i < A->size1; i++)
  114. for (size_t j = 0; j < A->size2; j++)
  115. gsl_matrix_set (res, i, j,
  116. gsl_matrix_get (A, i, j) - gsl_matrix_get (B, i, j));
  117. return res;
  118. }
  119. /**
  120. Multiplication d'une matrice par un scalaire
  121. @param A pointeur sur une matrice
  122. @param n scalaire par lequel on multiplie la matrice
  123. @return pointeur sur la matrice contenant n*A
  124. */
  125. gsl_matrix *
  126. matrix_mul_scale (
  127. const gsl_matrix * const A,
  128. double n)
  129. {
  130. gsl_matrix *res = gsl_matrix_alloc (A->size1, A->size2);
  131. a2ri_erreur_critique_si (res == NULL,
  132. "erreur allocation memoire pour res\nmatrix_scale");
  133. for (size_t i = 0; i < A->size1; i++)
  134. for (size_t j = 0; j < A->size2; j++)
  135. gsl_matrix_set (res, i, j, gsl_matrix_get (A, i, j) * n);
  136. return res;
  137. }
  138. /**
  139. Multiplication de deux matrices
  140. @param A pointeur sur la première matrice
  141. @param B pointeur sur la seconde matrice
  142. @return pointeur sur une matrice contenant la multiplication A*B
  143. @warning Erreur du programme si le nombre de colonne de la première matrice est différent du nombre de ligne de la seconde.
  144. */
  145. gsl_matrix *
  146. matrix_mul (
  147. const gsl_matrix * const A,
  148. const gsl_matrix * const B)
  149. {
  150. double alpha = 1.,
  151. beta = 0.;
  152. gsl_matrix *C = gsl_matrix_alloc (A->size1, B->size2);
  153. a2ri_erreur_critique_si (C == NULL,
  154. "erreur allocation memoire pour C\nmatrix_mul");
  155. gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, alpha, A, B, beta, C);
  156. return C;
  157. }
  158. /**
  159. Calcul de l'inverse d'une matrice
  160. @param m pointeur sur une matrice
  161. @return pointeur sur une matrice contenant l'inverse \f$A^{-1}\f$
  162. */
  163. gsl_matrix *
  164. matrix_inverse (
  165. const gsl_matrix * const m)
  166. {
  167. int s;
  168. gsl_permutation *p = gsl_permutation_alloc (m->size1);
  169. a2ri_erreur_critique_si (p == NULL,
  170. "erreur allocation memoire pour p\nmatrix_inverse");
  171. gsl_matrix *ludecomp = gsl_matrix_alloc (m->size1, m->size1);
  172. a2ri_erreur_critique_si (ludecomp == NULL,
  173. "erreur allocation memoire pour ludecomp\nmatrix_inverse");
  174. gsl_matrix *inv = gsl_matrix_alloc (m->size1, m->size1);
  175. a2ri_erreur_critique_si (inv == NULL,
  176. "erreur allocation memoire pour inv\nmatrix_inverse");
  177. gsl_matrix_memcpy (ludecomp, m);
  178. gsl_linalg_LU_decomp (ludecomp, p, &s);
  179. gsl_linalg_LU_invert (ludecomp, p, inv);
  180. gsl_matrix_free (ludecomp);
  181. gsl_permutation_free (p);
  182. return inv;
  183. }
  184. /**
  185. Affichage d'une matrice
  186. @param m pointeur sur une matrice
  187. @return aucun
  188. */
  189. void
  190. matrix_display (
  191. const gsl_matrix * const m)
  192. {
  193. printf ("[[\n");
  194. for (size_t i = 0; i < m->size1; i++)
  195. {
  196. for (size_t j = 0; j < m->size2; j++)
  197. printf ("%4.2lf\t", gsl_matrix_get (m, i, j));
  198. printf ("\n");
  199. }
  200. printf ("]]\n");
  201. }
  202. /**
  203. Initialisation d'une matrice à partir d'une liste de valeur
  204. @param data liste de valeur
  205. @param nbline nombre de ligne
  206. @param nbcol nombre de colonne
  207. @return pointeur sur la matrice initialisée avec la liste de valeur
  208. Exemple de code
  209. @code
  210. double data[]={1.0,2.0,3.0,4.0,5.0,6.0};
  211. gsl_matrix *mat=matrix_init(data,2,3);
  212. matrix_display(mat);
  213. @endcode
  214. donne le résultat suivant
  215. @code
  216. 1.0 2.0 3.0
  217. 4.0 5.0 6.0
  218. @endcode
  219. */
  220. gsl_matrix *
  221. matrix_init (
  222. double *data,
  223. int nbline,
  224. int nbcol)
  225. {
  226. gsl_matrix *m = gsl_matrix_alloc (nbline, nbcol);
  227. a2ri_erreur_critique_si (m == NULL,
  228. "erreur allocation memoire pour m\nmatrix_init");
  229. for (int i = 0; i < nbline; i++)
  230. for (int j = 0; j < nbcol; j++)
  231. gsl_matrix_set (m, i, j, data[i * nbcol + j]);
  232. return m;
  233. }
  234. /**
  235. Calcul de la transposé d'une matrice
  236. @param m pointeur sur une matrice
  237. @return pointeur sur une matrice contenant la transposé \f$A^T\f$
  238. */
  239. gsl_matrix *
  240. matrix_transpose (
  241. const gsl_matrix * const m)
  242. {
  243. gsl_matrix *ret = gsl_matrix_alloc (m->size2, m->size1);
  244. a2ri_erreur_critique_si (ret == NULL,
  245. "erreur allocation memoire pour ret\nmatrix_transpose");
  246. for (size_t i = 0; i < m->size1; i++)
  247. for (size_t j = 0; j < m->size2; j++)
  248. gsl_matrix_set (ret, j, i, gsl_matrix_get (m, i, j));
  249. return ret;
  250. }
  251. /**
  252. Calcul de la matrice de covariance
  253. @param data_p premier ensemble de point
  254. @param data_x second ensemble de point
  255. @param nbpoint nombre de point
  256. @return la matrice de covariance
  257. */
  258. //calcul de la matrice covariance
  259. //voir Besl p243
  260. gsl_matrix *
  261. cross_variance (
  262. const point3d * const data_p,
  263. const point3d * const data_x,
  264. int nbpoint)
  265. {
  266. point3d *centerP,
  267. *centerX,
  268. tempp,
  269. tempx;
  270. gsl_matrix *somme,
  271. *up,
  272. *ux,
  273. *mul = NULL,
  274. *pi,
  275. *xi;
  276. double d[3];
  277. somme = gsl_matrix_calloc (3, 3);
  278. a2ri_erreur_critique_si (somme == NULL,
  279. "erreur allocation memoire pour somme\ncross_variance");
  280. centerP = center_of_mass (data_p, nbpoint);
  281. centerX = center_of_mass (data_x, nbpoint);
  282. d[0] = centerP->x;
  283. d[1] = centerP->y;
  284. d[2] = centerP->z;
  285. up = matrix_init (d, 3, 1);
  286. d[0] = centerX->x;
  287. d[1] = centerX->y;
  288. d[2] = centerX->z;
  289. ux = matrix_init (d, 1, 3);
  290. for (int i = 0; i < nbpoint; i++)
  291. {
  292. //p_i-up
  293. tempp.x = data_p[i].x - gsl_matrix_get (up, 0, 0);
  294. tempp.y = data_p[i].y - gsl_matrix_get (up, 1, 0);
  295. tempp.z = data_p[i].z - gsl_matrix_get (up, 2, 0);
  296. //p_x-ux
  297. tempx.x = data_x[i].x - gsl_matrix_get (ux, 0, 0);
  298. tempx.y = data_x[i].y - gsl_matrix_get (ux, 0, 1);
  299. tempx.z = data_x[i].z - gsl_matrix_get (ux, 0, 2);
  300. d[0] = tempp.x;
  301. d[1] = tempp.y;
  302. d[2] = tempp.z;
  303. pi = matrix_init (d, 3, 1);
  304. d[0] = tempx.x;
  305. d[1] = tempx.y;
  306. d[2] = tempx.z;
  307. xi = matrix_init (d, 1, 3);
  308. //(p_i-up)(p_x-ux)
  309. mul = matrix_mul (pi, xi);
  310. //somme
  311. somme = matrix_add (somme, mul);
  312. gsl_matrix_free (pi);
  313. gsl_matrix_free (xi);
  314. }
  315. for (size_t i = 0; i < somme->size1; i++)
  316. for (size_t j = 0; j < somme->size2; j++)
  317. gsl_matrix_set (somme, i, j,
  318. gsl_matrix_get (somme, i, j) / (nbpoint * 1.0));
  319. free (centerP);
  320. free (centerX);
  321. gsl_matrix_free (up);
  322. gsl_matrix_free (ux);
  323. gsl_matrix_free (mul);
  324. return somme;
  325. }