matrix_factorisation.inl 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /// @ref gtx_matrix_factorisation
  2. namespace glm
  3. {
  4. template <length_t C, length_t R, typename T, qualifier Q>
  5. GLM_FUNC_QUALIFIER mat<C, R, T, Q> flipud(mat<C, R, T, Q> const& in)
  6. {
  7. mat<R, C, T, Q> tin = transpose(in);
  8. tin = fliplr(tin);
  9. mat<C, R, T, Q> out = transpose(tin);
  10. return out;
  11. }
  12. template <length_t C, length_t R, typename T, qualifier Q>
  13. GLM_FUNC_QUALIFIER mat<C, R, T, Q> fliplr(mat<C, R, T, Q> const& in)
  14. {
  15. mat<C, R, T, Q> out;
  16. for (length_t i = 0; i < C; i++)
  17. {
  18. out[i] = in[(C - i) - 1];
  19. }
  20. return out;
  21. }
  22. template <length_t C, length_t R, typename T, qualifier Q>
  23. GLM_FUNC_QUALIFIER void qr_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& q, mat<C, (C < R ? C : R), T, Q>& r)
  24. {
  25. // Uses modified Gram-Schmidt method
  26. // Source: https://en.wikipedia.org/wiki/Gram–Schmidt_process
  27. // And https://en.wikipedia.org/wiki/QR_decomposition
  28. //For all the linearly independs columns of the input...
  29. // (there can be no more linearly independents columns than there are rows.)
  30. for (length_t i = 0; i < (C < R ? C : R); i++)
  31. {
  32. //Copy in Q the input's i-th column.
  33. q[i] = in[i];
  34. //j = [0,i[
  35. // Make that column orthogonal to all the previous ones by substracting to it the non-orthogonal projection of all the previous columns.
  36. // Also: Fill the zero elements of R
  37. for (length_t j = 0; j < i; j++)
  38. {
  39. q[i] -= dot(q[i], q[j])*q[j];
  40. r[j][i] = 0;
  41. }
  42. //Now, Q i-th column is orthogonal to all the previous columns. Normalize it.
  43. q[i] = normalize(q[i]);
  44. //j = [i,C[
  45. //Finally, compute the corresponding coefficients of R by computing the projection of the resulting column on the other columns of the input.
  46. for (length_t j = i; j < C; j++)
  47. {
  48. r[j][i] = dot(in[j], q[i]);
  49. }
  50. }
  51. }
  52. template <length_t C, length_t R, typename T, qualifier Q>
  53. GLM_FUNC_QUALIFIER void rq_decompose(mat<C, R, T, Q> const& in, mat<(C < R ? C : R), R, T, Q>& r, mat<C, (C < R ? C : R), T, Q>& q)
  54. {
  55. // From https://en.wikipedia.org/wiki/QR_decomposition:
  56. // The RQ decomposition transforms a matrix A into the product of an upper triangular matrix R (also known as right-triangular) and an orthogonal matrix Q. The only difference from QR decomposition is the order of these matrices.
  57. // QR decomposition is Gram–Schmidt orthogonalization of columns of A, started from the first column.
  58. // RQ decomposition is Gram–Schmidt orthogonalization of rows of A, started from the last row.
  59. mat<R, C, T, Q> tin = transpose(in);
  60. tin = fliplr(tin);
  61. mat<R, (C < R ? C : R), T, Q> tr;
  62. mat<(C < R ? C : R), C, T, Q> tq;
  63. qr_decompose(tin, tq, tr);
  64. tr = fliplr(tr);
  65. r = transpose(tr);
  66. r = fliplr(r);
  67. tq = fliplr(tq);
  68. q = transpose(tq);
  69. }
  70. } //namespace glm