| 97 | |
| 98 | template<typename T> |
| 99 | Array<T> leastSquares(const Array<T> &a, const Array<T> &b) { |
| 100 | int M = a.dims()[0]; |
| 101 | int N = a.dims()[1]; |
| 102 | int K = b.dims()[1]; |
| 103 | int MN = min(M, N); |
| 104 | |
| 105 | Array<T> B = createEmptyArray<T>(dim4()); |
| 106 | gpu_blas_trsm_func<T> gpu_blas_trsm; |
| 107 | |
| 108 | cl_event event; |
| 109 | cl_command_queue queue = getQueue()(); |
| 110 | |
| 111 | if (M < N) { |
| 112 | #define UNMQR 0 // FIXME: UNMQR == 1 should be faster but does not work |
| 113 | |
| 114 | // Least squres for this case is solved using the following |
| 115 | // solve(A, B) == matmul(Q, Xpad); |
| 116 | // Where: |
| 117 | // Xpad == pad(Xt, N - M, 1); |
| 118 | // Xt == tri_solve(R1, B); |
| 119 | // R1 == R(seq(M), seq(M)); |
| 120 | // transpose(A) == matmul(Q, R); |
| 121 | |
| 122 | // QR is performed on the transpose of A |
| 123 | Array<T> A = transpose<T>(a, true); |
| 124 | |
| 125 | #if UNMQR |
| 126 | const dim4 NullShape(0, 0, 0, 0); |
| 127 | dim4 endPadding(N - b.dims()[0], K - b.dims()[1], 0, 0); |
| 128 | B = (endPadding == NullShape |
| 129 | ? copyArray(b) |
| 130 | : padArrayBorders(b, NullShape, endPadding, AF_PAD_ZERO)); |
| 131 | B.resetDims(dim4(M, K)); |
| 132 | #else |
| 133 | B = copyArray<T>(b); |
| 134 | #endif |
| 135 | |
| 136 | int NB = magma_get_geqrf_nb<T>(A.dims()[1]); |
| 137 | int NUM = (2 * MN + ((M + 31) / 32) * 32) * NB; |
| 138 | Array<T> tmp = createEmptyArray<T>(dim4(NUM)); |
| 139 | |
| 140 | vector<T> h_tau(MN); |
| 141 | |
| 142 | int info = 0; |
| 143 | Buffer *dA = A.get(); |
| 144 | Buffer *dT = tmp.get(); |
| 145 | Buffer *dB = B.get(); |
| 146 | |
| 147 | magma_geqrf3_gpu<T>(A.dims()[0], A.dims()[1], (*dA)(), A.getOffset(), |
| 148 | A.strides()[1], &h_tau[0], (*dT)(), tmp.getOffset(), |
| 149 | getQueue()(), &info); |
| 150 | |
| 151 | A.resetDims(dim4(M, M)); |
| 152 | |
| 153 | magmablas_swapdblk<T>(MN - 1, NB, (*dA)(), A.getOffset(), |
| 154 | A.strides()[1], 1, (*dT)(), |
| 155 | tmp.getOffset() + MN * NB, NB, 0, queue); |
| 156 |
nothing calls this directly
no test coverage detected