| 1007 | // T can be CompMatr2 or CompMatr |
| 1008 | template <typename T> |
| 1009 | void anyCtrlTwoOrAnyTargDenseMatr(Qureg qureg, vector<int> ctrls, vector<int> ctrlStates, vector<int> targs, T matr, bool conj, bool transp) { |
| 1010 | |
| 1011 | // node has nothing to do if all local amps violate control condition |
| 1012 | if (!doAnyLocalStatesHaveQubitValues(qureg, ctrls, ctrlStates)) |
| 1013 | return; |
| 1014 | |
| 1015 | // skip straight to embarrasingly parallel simulation if possible |
| 1016 | if (!doesGateRequireComm(qureg, targs)) { |
| 1017 | |
| 1018 | // using only the suffix ctrls |
| 1019 | removePrefixQubitsAndStates(qureg, ctrls, ctrlStates); |
| 1020 | anyCtrlTwoOrAnyTargDenseMatrOnSuffix(qureg, ctrls, ctrlStates, targs, matr, conj, transp); |
| 1021 | return; |
| 1022 | } |
| 1023 | |
| 1024 | // find suffix positions for all prefix targs, moving colliding ctrls out of the way |
| 1025 | auto [newCtrls, newTargs] = getCtrlsAndTargsSwappedToMinSuffix(qureg, ctrls, targs); |
| 1026 | |
| 1027 | // only unmoved ctrls can be applied to the swaps, to accelerate them |
| 1028 | auto [unmovedCtrls, unmovedCtrlStates] = getNonSwappedCtrlsAndStates(ctrls, ctrlStates, newCtrls); |
| 1029 | |
| 1030 | /// @todo |
| 1031 | /// above, we track which control qubits are un-targeted by the SWAPs; such controls can be |
| 1032 | /// seen as 'meta' to the entire operation, and so SHOULD be passable to the SWAPs below in |
| 1033 | /// order to accelerate them (since more ctrls = fewer comm). However, this is strangely not |
| 1034 | /// working; controlling the SWAPs upon these 'meta' control qubits is breaking the unit tests! |
| 1035 | /// Until we better understand this, we disable this optimisation by removing all SWAP controls. |
| 1036 | unmovedCtrls = {}; |
| 1037 | unmovedCtrlStates = {}; |
| 1038 | |
| 1039 | // perform necessary swaps to move all targets into suffix, invoking communication (swaps are real, so no need to conj) |
| 1040 | anyCtrlMultiSwapBetweenPrefixAndSuffix(qureg, unmovedCtrls, unmovedCtrlStates, targs, newTargs); |
| 1041 | |
| 1042 | // if the moved ctrls do not eliminate this node's need for local simulation... |
| 1043 | if (doAnyLocalStatesHaveQubitValues(qureg, newCtrls, ctrlStates)) { |
| 1044 | |
| 1045 | // perform embarrassingly parallel simulation using only the new suffix ctrls |
| 1046 | removePrefixQubitsAndStates(qureg, newCtrls, ctrlStates); |
| 1047 | anyCtrlTwoOrAnyTargDenseMatrOnSuffix(qureg, newCtrls, ctrlStates, newTargs, matr, conj, transp); |
| 1048 | } |
| 1049 | |
| 1050 | // undo swaps, again invoking communication |
| 1051 | anyCtrlMultiSwapBetweenPrefixAndSuffix(qureg, unmovedCtrls, unmovedCtrlStates, targs, newTargs); |
| 1052 | } |
| 1053 | |
| 1054 | |
| 1055 | void localiser_statevec_anyCtrlTwoTargDenseMatr(Qureg qureg, vector<int> ctrls, vector<int> ctrlStates, int targ1, int targ2, CompMatr2 matr, bool conj, bool transp) { |
no test coverage detected