| 255 | |
| 256 | template<typename T> |
| 257 | Array<T> triangleSolve(const Array<T> &A, const Array<T> &b, |
| 258 | const af_mat_prop options) { |
| 259 | gpu_blas_trsm_func<T> gpu_blas_trsm; |
| 260 | |
| 261 | Array<T> B = copyArray<T>(b); |
| 262 | |
| 263 | int N = B.dims()[0]; |
| 264 | int NRHS = B.dims()[1]; |
| 265 | |
| 266 | const Buffer *A_buf = A.get(); |
| 267 | Buffer *B_buf = B.get(); |
| 268 | |
| 269 | cl_event event = 0; |
| 270 | cl_command_queue queue = getQueue()(); |
| 271 | |
| 272 | if (getActivePlatformVendor() == AFCL_PLATFORM_NVIDIA && |
| 273 | (options & AF_MAT_UPPER)) { |
| 274 | Array<T> AT = transpose<T>(A, true); |
| 275 | |
| 276 | cl::Buffer *AT_buf = AT.get(); |
| 277 | OPENCL_BLAS_CHECK(gpu_blas_trsm( |
| 278 | OPENCL_BLAS_SIDE_LEFT, OPENCL_BLAS_TRIANGLE_LOWER, |
| 279 | OPENCL_BLAS_CONJ_TRANS, |
| 280 | options & AF_MAT_DIAG_UNIT ? OPENCL_BLAS_UNIT_DIAGONAL |
| 281 | : OPENCL_BLAS_NON_UNIT_DIAGONAL, |
| 282 | N, NRHS, scalar<T>(1), (*AT_buf)(), AT.getOffset(), AT.strides()[1], |
| 283 | (*B_buf)(), B.getOffset(), B.strides()[1], 1, &queue, 0, nullptr, |
| 284 | &event)); |
| 285 | } else { |
| 286 | OPENCL_BLAS_CHECK(gpu_blas_trsm( |
| 287 | OPENCL_BLAS_SIDE_LEFT, |
| 288 | options & AF_MAT_LOWER ? OPENCL_BLAS_TRIANGLE_LOWER |
| 289 | : OPENCL_BLAS_TRIANGLE_UPPER, |
| 290 | OPENCL_BLAS_NO_TRANS, |
| 291 | options & AF_MAT_DIAG_UNIT ? OPENCL_BLAS_UNIT_DIAGONAL |
| 292 | : OPENCL_BLAS_NON_UNIT_DIAGONAL, |
| 293 | N, NRHS, scalar<T>(1), (*A_buf)(), A.getOffset(), A.strides()[1], |
| 294 | (*B_buf)(), B.getOffset(), B.strides()[1], 1, &queue, 0, nullptr, |
| 295 | &event)); |
| 296 | } |
| 297 | |
| 298 | return B; |
| 299 | } |
| 300 | |
| 301 | template<typename T> |
| 302 | Array<T> solve(const Array<T> &a, const Array<T> &b, |