| 63 | |
| 64 | template<typename T, typename Tr> |
| 65 | void svd(Array<T> &arrU, Array<Tr> &arrS, Array<T> &arrVT, Array<T> &arrA, |
| 66 | bool want_vectors = true) { |
| 67 | dim4 idims = arrA.dims(); |
| 68 | dim4 istrides = arrA.strides(); |
| 69 | |
| 70 | const int m = static_cast<int>(idims[0]); |
| 71 | const int n = static_cast<int>(idims[1]); |
| 72 | const int ldda = static_cast<int>(istrides[1]); |
| 73 | const int lda = m; |
| 74 | const int min_mn = std::min(m, n); |
| 75 | const int ldu = m; |
| 76 | const int ldvt = n; |
| 77 | |
| 78 | const int nb = magma_get_gebrd_nb<T>(n); |
| 79 | const int lwork = (m + n) * nb; |
| 80 | |
| 81 | cpu_lapack_lacpy_func<T> cpu_lapack_lacpy; |
| 82 | cpu_lapack_bdsqr_work_func<T> cpu_lapack_bdsqr_work; |
| 83 | cpu_lapack_ungbr_work_func<T> cpu_lapack_ungbr_work; |
| 84 | cpu_lapack_lamch_func<Tr> cpu_lapack_lamch; |
| 85 | |
| 86 | // Get machine constants |
| 87 | static const double eps = cpu_lapack_lamch('P'); |
| 88 | static const double smlnum = std::sqrt(cpu_lapack_lamch('S')) / eps; |
| 89 | static const double bignum = 1. / smlnum; |
| 90 | |
| 91 | Tr anrm = abs(getScalar<T>(reduce_all<af_max_t, T, T>(arrA))); |
| 92 | |
| 93 | T scale = scalar<T>(1); |
| 94 | static const int ione = 1; |
| 95 | static const int izero = 0; |
| 96 | |
| 97 | bool iscl = false; |
| 98 | if (anrm > 0. && anrm < smlnum) { |
| 99 | iscl = true; |
| 100 | scale = scalar<T>(calc_scale<Tr>(anrm, smlnum)); |
| 101 | } else if (anrm > bignum) { |
| 102 | iscl = true; |
| 103 | scale = scalar<T>(calc_scale<Tr>(anrm, bignum)); |
| 104 | } |
| 105 | |
| 106 | if (iscl == 1) { multiply_inplace(arrA, abs(scale)); } |
| 107 | |
| 108 | int nru = 0; |
| 109 | int ncvt = 0; |
| 110 | |
| 111 | // Instead of copying U, S, VT, and A to the host and copying the results |
| 112 | // back to the device, create a pointer that's mapped to device memory where |
| 113 | // the computation can directly happen |
| 114 | T *mappedA = static_cast<T *>(getQueue().enqueueMapBuffer( |
| 115 | *arrA.get(), CL_FALSE, CL_MAP_READ, sizeof(T) * arrA.getOffset(), |
| 116 | sizeof(T) * arrA.elements())); |
| 117 | std::vector<T> tauq(min_mn), taup(min_mn); |
| 118 | std::vector<T> work(lwork); |
| 119 | Tr *mappedS0 = (Tr *)getQueue().enqueueMapBuffer( |
| 120 | *arrS.get(), CL_TRUE, CL_MAP_WRITE, sizeof(Tr) * arrS.getOffset(), |
| 121 | sizeof(Tr) * arrS.elements()); |
| 122 | std::vector<Tr> s1(min_mn - 1); |
nothing calls this directly
no test coverage detected