| 28 | |
| 29 | template<typename T> |
| 30 | void qr(Array<T> &q, Array<T> &r, Array<T> &t, const Array<T> &orig) { |
| 31 | if (OpenCLCPUOffload()) { return cpu::qr(q, r, t, orig); } |
| 32 | |
| 33 | const dim4 NullShape(0, 0, 0, 0); |
| 34 | |
| 35 | dim4 iDims = orig.dims(); |
| 36 | int M = iDims[0]; |
| 37 | int N = iDims[1]; |
| 38 | |
| 39 | dim4 endPadding(M - iDims[0], max(M, N) - iDims[1], 0, 0); |
| 40 | Array<T> in = |
| 41 | (endPadding == NullShape |
| 42 | ? copyArray(orig) |
| 43 | : padArrayBorders(orig, NullShape, endPadding, AF_PAD_ZERO)); |
| 44 | in.resetDims(iDims); |
| 45 | |
| 46 | int MN = std::min(M, N); |
| 47 | int NB = magma_get_geqrf_nb<T>(M); |
| 48 | |
| 49 | int NUM = (2 * MN + ((N + 31) / 32) * 32) * NB; |
| 50 | Array<T> tmp = createEmptyArray<T>(dim4(NUM)); |
| 51 | |
| 52 | std::vector<T> h_tau(MN); |
| 53 | |
| 54 | int info = 0; |
| 55 | cl::Buffer *in_buf = in.get(); |
| 56 | cl::Buffer *dT = tmp.get(); |
| 57 | |
| 58 | magma_geqrf3_gpu<T>(M, N, (*in_buf)(), in.getOffset(), in.strides()[1], |
| 59 | &h_tau[0], (*dT)(), tmp.getOffset(), getQueue()(), |
| 60 | &info); |
| 61 | |
| 62 | r = createEmptyArray<T>(in.dims()); |
| 63 | kernel::triangle<T>(r, in, true, false); |
| 64 | |
| 65 | cl::Buffer *r_buf = r.get(); |
| 66 | magmablas_swapdblk<T>(MN - 1, NB, (*r_buf)(), r.getOffset(), r.strides()[1], |
| 67 | 1, (*dT)(), tmp.getOffset() + MN * NB, NB, 0, |
| 68 | getQueue()()); |
| 69 | |
| 70 | q = in; // No need to copy |
| 71 | q.resetDims(dim4(M, M)); |
| 72 | cl::Buffer *q_buf = q.get(); |
| 73 | |
| 74 | magma_ungqr_gpu<T>(q.dims()[0], q.dims()[1], std::min(M, N), (*q_buf)(), |
| 75 | q.getOffset(), q.strides()[1], &h_tau[0], (*dT)(), |
| 76 | tmp.getOffset(), NB, getQueue()(), &info); |
| 77 | |
| 78 | t = createHostDataArray(dim4(MN), &h_tau[0]); |
| 79 | } |
| 80 | |
| 81 | template<typename T> |
| 82 | Array<T> qr_inplace(Array<T> &in) { |
nothing calls this directly
no test coverage detected