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