| 34 | // T can be CompMatr, CompMatr1, CompMatr2, DiagMatr, DiagMatr1, DiagMatr2 |
| 35 | template <class T> |
| 36 | void validateAndApplyAnyCtrlAnyTargUnitaryMatrix(Qureg qureg, int* ctrls, int* states, int numCtrls, int* targs, int numTargs, T matr, const char* caller) { |
| 37 | validate_quregFields(qureg, caller); |
| 38 | validate_controlsAndTargets(qureg, ctrls, numCtrls, targs, numTargs, caller); |
| 39 | validate_controlStates(states, numCtrls, caller); |
| 40 | validate_matrixDimMatchesTargets(matr, numTargs, caller); // also checks fields and is-synced |
| 41 | validate_matrixIsUnitary(matr, caller); // harmlessly rechecks fields and is-synced |
| 42 | if (util_isDenseMatrixType<T>()) |
| 43 | validate_mixedAmpsFitInNode(qureg, numTargs, caller); |
| 44 | |
| 45 | auto ctrlVec = util_getVector(ctrls, numCtrls); |
| 46 | auto stateVec = util_getVector(states, numCtrls); |
| 47 | auto targVec = util_getVector(targs, numTargs); |
| 48 | |
| 49 | bool conj = false; |
| 50 | localiser_statevec_anyCtrlAnyTargAnyMatr(qureg, ctrlVec, stateVec, targVec, matr, conj); |
| 51 | |
| 52 | if (!qureg.isDensityMatrix) |
| 53 | return; |
| 54 | |
| 55 | conj = true; |
| 56 | ctrlVec = util_getBraQubits(ctrlVec, qureg); |
| 57 | targVec = util_getBraQubits(targVec, qureg); |
| 58 | localiser_statevec_anyCtrlAnyTargAnyMatr(qureg, ctrlVec, stateVec, targVec, matr, conj); |
| 59 | |
| 60 | /// @todo |
| 61 | /// the above logic always performs two in-turn operations upon density matrices, |
| 62 | /// though when matr is diagonal (DiagMatr*), they can be trivially combined into |
| 63 | /// a single operation which enumerates the state only once. We perform this |
| 64 | /// optimisation for FullStateDiagMatr elsewhere. Consider optimising here too! |
| 65 | } |
| 66 | |
| 67 | |
| 68 |
no test coverage detected