| 611 | |
| 612 | |
| 613 | void localiser_densmatr_setAmps(qcomp** inAmps, Qureg qureg, qindex startRow, qindex startCol, qindex numRows, qindex numCols) { |
| 614 | assert_localiserGivenDensMatr(qureg); |
| 615 | |
| 616 | /// @todo improve the performance! |
| 617 | /// this function works by simply enumerating each column of inAmps |
| 618 | /// (which requires explicit preparation, because inAmps is passed |
| 619 | /// column-wise, rather than row-wise), passing each to the above |
| 620 | /// statevec routine. It is ergo similar to the naive method used by |
| 621 | /// localiser_densmatr_getAmps(), though is embarrassingly parallel. |
| 622 | /// This func allocates temporary memory as large as numRows*numCols |
| 623 | /// (which could be an entire Qureg's worth), and serially computes |
| 624 | /// the transpose (which can be as bad as serial iteration of the |
| 625 | /// whole qureg). This is grossly inefficient, and worse than merely |
| 626 | /// parallel-overwriting CPU memory then copying to GPU. |
| 627 | |
| 628 | vector<vector<qcomp>> tempAmps; |
| 629 | util_tryAllocMatrix(tempAmps, numCols, numRows, error_localiserFailedToAllocTempMemory); // transpose of inAmps |
| 630 | |
| 631 | // serially overwrite tempAmps = transpose(inAmps) |
| 632 | for (qindex c=0; c<numCols; c++) |
| 633 | for (qindex r=0; r<numRows; r++) |
| 634 | tempAmps[c][r] = inAmps[r][c]; // writes contiguous, reads strided |
| 635 | |
| 636 | // call the statevector function upon each column |
| 637 | for (qindex c=0; c<numCols; c++) { |
| 638 | qindex flatInd = util_getGlobalFlatIndex(qureg, startRow, startCol + c); |
| 639 | localiser_statevec_setAmps(tempAmps[c].data(), qureg, flatInd, numRows); |
| 640 | } |
| 641 | } |
| 642 | |
| 643 | |
| 644 | void localiser_densmatr_setAmpsToPauliStrSum(Qureg qureg, PauliStrSum sum) { |
no test coverage detected